Correctly migrate to fs-extra
authorChocobozzz <me@florianbigard.com>
Mon, 27 Aug 2018 14:23:34 +0000 (16:23 +0200)
committerChocobozzz <me@florianbigard.com>
Mon, 27 Aug 2018 14:23:34 +0000 (16:23 +0200)
29 files changed:
package.json
scripts/prune-storage.ts
server/controllers/api/config.ts
server/controllers/api/videos/import.ts
server/controllers/api/videos/index.ts
server/helpers/captions-utils.ts
server/helpers/core-utils.ts
server/helpers/ffmpeg-utils.ts
server/helpers/image-utils.ts
server/helpers/utils.ts
server/helpers/webtorrent.ts
server/initializers/installer.ts
server/initializers/migrations/0075-video-resolutions.ts
server/initializers/migrator.ts
server/lib/cache/abstract-video-static-file-cache.ts
server/lib/client-html.ts
server/lib/job-queue/handlers/video-import.ts
server/lib/schedulers/youtube-dl-update-scheduler.ts
server/models/avatar/avatar.ts
server/models/video/video-caption.ts
server/models/video/video.ts
server/tests/feeds/feeds.ts
server/tests/utils/feeds/feeds.ts
server/tests/utils/miscs/miscs.ts
server/tests/utils/users/accounts.ts
server/tests/utils/videos/videos.ts
server/tools/import-videos.ts
server/tools/upload.ts
yarn.lock

index 635ceaf76aa0c3d1e783abc8532deb086e3343df..c452a9f52765f0ccbea6e8620a159b8b381f9100 100644 (file)
     "redis": "^2.8.0",
     "reflect-metadata": "^0.1.10",
     "request": "^2.81.0",
-    "rimraf": "^2.5.4",
     "safe-buffer": "^5.0.1",
     "scripty": "^1.5.0",
     "sequelize": "4.38.0",
     "@types/config": "^0.0.34",
     "@types/express": "^4.0.35",
     "@types/express-rate-limit": "^2.9.3",
+    "@types/fs-extra": "^5.0.4",
     "@types/libxmljs": "^0.18.0",
     "@types/lodash": "^4.14.64",
     "@types/magnet-uri": "^5.1.1",
index bc59da6afb383d124ca6e5913274d2d51d2d64b4..5722838685d2277da1a112a14051482786e982da 100755 (executable)
@@ -1,9 +1,9 @@
 import * as prompt from 'prompt'
 import { join } from 'path'
-import { readdirPromise, unlinkPromise } from '../server/helpers/core-utils'
 import { CONFIG } from '../server/initializers/constants'
 import { VideoModel } from '../server/models/video/video'
 import { initDatabaseModels } from '../server/initializers'
+import { remove, readdir } from 'fs-extra'
 
 run()
   .then(() => process.exit(0))
@@ -39,7 +39,7 @@ async function run () {
     console.log('Processing delete...\n')
 
     for (const path of toDelete) {
-      await unlinkPromise(path)
+      await remove(path)
     }
 
     console.log('Done!')
@@ -49,7 +49,7 @@ async function run () {
 }
 
 async function pruneDirectory (directory: string) {
-  const files = await readdirPromise(directory)
+  const files = await readdir(directory)
 
   const toDelete: string[] = []
   for (const file of files) {
index e0539c414fe2a39ddf5c76c98ebeefd3501f57ce..b25f739bb4b96b3fae20c9354dc728eb3ae878cb 100644 (file)
@@ -3,13 +3,13 @@ import { omit } from 'lodash'
 import { ServerConfig, UserRight } from '../../../shared'
 import { About } from '../../../shared/models/server/about.model'
 import { CustomConfig } from '../../../shared/models/server/custom-config.model'
-import { unlinkPromise, writeFilePromise } from '../../helpers/core-utils'
 import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup'
 import { CONFIG, CONSTRAINTS_FIELDS, reloadConfig } from '../../initializers'
 import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares'
 import { customConfigUpdateValidator } from '../../middlewares/validators/config'
 import { ClientHtml } from '../../lib/client-html'
 import { auditLoggerFactory, CustomConfigAuditView } from '../../helpers/audit-logger'
+import { remove, writeJSON } from 'fs-extra'
 
 const packageJSON = require('../../../../package.json')
 const configRouter = express.Router()
@@ -130,7 +130,7 @@ async function getCustomConfig (req: express.Request, res: express.Response, nex
 }
 
 async function deleteCustomConfig (req: express.Request, res: express.Response, next: express.NextFunction) {
-  await unlinkPromise(CONFIG.CUSTOM_FILE)
+  await remove(CONFIG.CUSTOM_FILE)
 
   auditLogger.delete(
     res.locals.oauth.token.User.Account.Actor.getIdentifier(),
@@ -163,7 +163,7 @@ async function updateCustomConfig (req: express.Request, res: express.Response,
   toUpdateJSON.instance['short_description'] = toUpdate.instance.shortDescription
   toUpdateJSON.instance['default_nsfw_policy'] = toUpdate.instance.defaultNSFWPolicy
 
-  await writeFilePromise(CONFIG.CUSTOM_FILE, JSON.stringify(toUpdateJSON, undefined, 2))
+  await writeJSON(CONFIG.CUSTOM_FILE, toUpdateJSON, { spaces: 2 })
 
   reloadConfig()
   ClientHtml.invalidCache()
index b2f73fa48289ea0b7124c725ce91b6e4b18b60fa..44f15ef74bbe9d286e1e7d6272ce0c0e3a6f9338 100644 (file)
@@ -27,8 +27,8 @@ import { FilteredModelAttributes } from 'sequelize-typescript/lib/models/Model'
 import { VideoChannelModel } from '../../../models/video/video-channel'
 import * as Bluebird from 'bluebird'
 import * as parseTorrent from 'parse-torrent'
-import { readFileBufferPromise, renamePromise } from '../../../helpers/core-utils'
 import { getSecureTorrentName } from '../../../helpers/utils'
+import { readFile, rename } from 'fs-extra'
 
 const auditLogger = auditLoggerFactory('video-imports')
 const videoImportsRouter = express.Router()
@@ -78,10 +78,10 @@ async function addTorrentImport (req: express.Request, res: express.Response, to
 
     // Rename the torrent to a secured name
     const newTorrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, getSecureTorrentName(torrentName))
-    await renamePromise(torrentfile.path, newTorrentPath)
+    await rename(torrentfile.path, newTorrentPath)
     torrentfile.path = newTorrentPath
 
-    const buf = await readFileBufferPromise(torrentfile.path)
+    const buf = await readFile(torrentfile.path)
     const parsedTorrent = parseTorrent(buf)
 
     videoName = isArray(parsedTorrent.name) ? parsedTorrent.name[ 0 ] : parsedTorrent.name as string
index e973aa43f797c0d5227a2ae560015c331fdbf5ee..a86cf4f9986ae49b076bb9675b6a065a30cad557 100644 (file)
@@ -1,7 +1,6 @@
 import * as express from 'express'
 import { extname, join } from 'path'
 import { VideoCreate, VideoPrivacy, VideoState, VideoUpdate } from '../../../../shared'
-import { renamePromise } from '../../../helpers/core-utils'
 import { getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils'
 import { processImage } from '../../../helpers/image-utils'
 import { logger } from '../../../helpers/logger'
@@ -56,6 +55,7 @@ import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-u
 import { videoCaptionsRouter } from './captions'
 import { videoImportsRouter } from './import'
 import { resetSequelizeInstance } from '../../../helpers/database-utils'
+import { rename } from 'fs-extra'
 
 const auditLogger = auditLoggerFactory('videos')
 const videosRouter = express.Router()
@@ -194,7 +194,7 @@ async function addVideo (req: express.Request, res: express.Response) {
   // Move physical file
   const videoDir = CONFIG.STORAGE.VIDEOS_DIR
   const destination = join(videoDir, video.getVideoFilename(videoFile))
-  await renamePromise(videoPhysicalFile.path, destination)
+  await rename(videoPhysicalFile.path, destination)
   // This is important in case if there is another attempt in the retry process
   videoPhysicalFile.filename = video.getVideoFilename(videoFile)
   videoPhysicalFile.path = destination
index 20c9fe5aa436efb48cb45128c1c97ec9f2d0c1f5..660dce65c3c5c0292dd3e680775c3356542300a7 100644 (file)
@@ -1,9 +1,8 @@
-import { renamePromise, unlinkPromise } from './core-utils'
 import { join } from 'path'
 import { CONFIG } from '../initializers'
 import { VideoCaptionModel } from '../models/video/video-caption'
 import * as srt2vtt from 'srt-to-vtt'
-import { createReadStream, createWriteStream } from 'fs-extra'
+import { createReadStream, createWriteStream, remove, rename } from 'fs-extra'
 
 async function moveAndProcessCaptionFile (physicalFile: { filename: string, path: string }, videoCaption: VideoCaptionModel) {
   const videoCaptionsDir = CONFIG.STORAGE.CAPTIONS_DIR
@@ -12,9 +11,9 @@ async function moveAndProcessCaptionFile (physicalFile: { filename: string, path
   // Convert this srt file to vtt
   if (physicalFile.path.endsWith('.srt')) {
     await convertSrtToVtt(physicalFile.path, destination)
-    await unlinkPromise(physicalFile.path)
+    await remove(physicalFile.path)
   } else { // Just move the vtt file
-    await renamePromise(physicalFile.path, destination)
+    await rename(physicalFile.path, destination)
   }
 
   // This is important in case if there is another attempt in the retry process
index 9830d41a89bdc375443d3587447d026c50c1d9f9..f5ef187fe73ccc29841e9b5786d8eb532de3d9ec 100644 (file)
@@ -6,7 +6,6 @@
 import * as bcrypt from 'bcrypt'
 import * as createTorrent from 'create-torrent'
 import { createHash, pseudoRandomBytes } from 'crypto'
-import { copyFile, readdir, readFile, rename, stat, Stats, unlink, writeFile, mkdirp } from 'fs-extra'
 import { isAbsolute, join } from 'path'
 import * as pem from 'pem'
 import * as rimraf from 'rimraf'
@@ -168,14 +167,6 @@ function promisify2WithVoid<T, U> (func: (arg1: T, arg2: U, cb: (err: any) => vo
   }
 }
 
-const copyFilePromise = promisify2WithVoid<string, string>(copyFile)
-const readFileBufferPromise = promisify1<string, Buffer>(readFile)
-const unlinkPromise = promisify1WithVoid<string>(unlink)
-const renamePromise = promisify2WithVoid<string, string>(rename)
-const writeFilePromise = promisify2WithVoid<string, any>(writeFile)
-const readdirPromise = promisify1<string, string[]>(readdir)
-const mkdirpPromise = promisify1<string, string>(mkdirp)
-// we cannot modify the Promise types, so we should make the promisify instance check mkdirp
 const pseudoRandomBytesPromise = promisify1<number, Buffer>(pseudoRandomBytes)
 const createPrivateKey = promisify1<number, { key: string }>(pem.createPrivateKey)
 const getPublicKey = promisify1<string, { publicKey: string }>(pem.getPublicKey)
@@ -183,8 +174,6 @@ const bcryptComparePromise = promisify2<any, string, boolean>(bcrypt.compare)
 const bcryptGenSaltPromise = promisify1<number, string>(bcrypt.genSalt)
 const bcryptHashPromise = promisify2<any, string | number, string>(bcrypt.hash)
 const createTorrentPromise = promisify2<string, any, any>(createTorrent)
-const rimrafPromise = promisify1WithVoid<string>(rimraf)
-const statPromise = promisify1<string, Stats>(stat)
 
 // ---------------------------------------------------------------------------
 
@@ -202,20 +191,11 @@ export {
   promisify0,
   promisify1,
 
-  copyFilePromise,
-  readdirPromise,
-  readFileBufferPromise,
-  unlinkPromise,
-  renamePromise,
-  writeFilePromise,
-  mkdirpPromise,
   pseudoRandomBytesPromise,
   createPrivateKey,
   getPublicKey,
   bcryptComparePromise,
   bcryptGenSaltPromise,
   bcryptHashPromise,
-  createTorrentPromise,
-  rimrafPromise,
-  statPromise
+  createTorrentPromise
 }
index 8936005e0e00e9379aa3429c001e05be034d59b1..7c45f36326de30ba57b6d143d8e8258d9c2e8623 100644 (file)
@@ -1,11 +1,11 @@
 import * as ffmpeg from 'fluent-ffmpeg'
 import { join } from 'path'
 import { VideoResolution } from '../../shared/models/videos'
-import { CONFIG, VIDEO_TRANSCODING_FPS, FFMPEG_NICE } from '../initializers'
-import { unlinkPromise } from './core-utils'
+import { CONFIG, FFMPEG_NICE, VIDEO_TRANSCODING_FPS } from '../initializers'
 import { processImage } from './image-utils'
 import { logger } from './logger'
 import { checkFFmpegEncoders } from '../initializers/checker'
+import { remove } from 'fs-extra'
 
 function computeResolutionsToTranscode (videoFileHeight: number) {
   const resolutionsEnabled: number[] = []
@@ -90,7 +90,7 @@ async function generateImageFromVideoFile (fromPath: string, folder: string, ima
     logger.error('Cannot generate image from video %s.', fromPath, { err })
 
     try {
-      await unlinkPromise(pendingImagePath)
+      await remove(pendingImagePath)
     } catch (err) {
       logger.debug('Cannot remove pending image path after generation error.', { err })
     }
index 0065f4210319866683fd931e9b8652276fe2aba4..3eaa674ed98e4bf67fa0db0026045a36885a045f 100644 (file)
@@ -1,6 +1,6 @@
 import 'multer'
 import * as sharp from 'sharp'
-import { unlinkPromise } from './core-utils'
+import { remove } from 'fs-extra'
 
 async function processImage (
   physicalFile: { path: string },
@@ -11,7 +11,7 @@ async function processImage (
     .resize(newSize.width, newSize.height)
     .toFile(destination)
 
-  await unlinkPromise(physicalFile.path)
+  await remove(physicalFile.path)
 }
 
 // ---------------------------------------------------------------------------
index 703e5788744889c74315e3646c626672ab14736b..a1ed8e72df461650e7f697c7bebf8cc94b62a5a2 100644 (file)
@@ -2,13 +2,14 @@ import { ResultList } from '../../shared'
 import { CONFIG } from '../initializers'
 import { ActorModel } from '../models/activitypub/actor'
 import { ApplicationModel } from '../models/application/application'
-import { pseudoRandomBytesPromise, sha256, unlinkPromise } from './core-utils'
+import { pseudoRandomBytesPromise, sha256 } from './core-utils'
 import { logger } from './logger'
 import { join } from 'path'
 import { Instance as ParseTorrent } from 'parse-torrent'
+import { remove } from 'fs-extra'
 
 function deleteFileAsync (path: string) {
-  unlinkPromise(path)
+  remove(path)
     .catch(err => logger.error('Cannot delete the file %s asynchronously.', path, { err }))
 }
 
index 1c0d00d70d33e04a58fee3747f66d856cbbf4e00..1c0cc7058a4389ed31c3749f24310b5a422f963a 100644 (file)
@@ -1,10 +1,9 @@
 import { logger } from './logger'
 import { generateVideoTmpPath } from './utils'
 import * as WebTorrent from 'webtorrent'
-import { createWriteStream } from 'fs-extra'
+import { createWriteStream, remove } from 'fs-extra'
 import { CONFIG } from '../initializers'
 import { join } from 'path'
-import { unlinkPromise } from './core-utils'
 
 function downloadWebTorrentVideo (target: { magnetUri: string, torrentName: string }) {
   const id = target.magnetUri || target.torrentName
@@ -29,11 +28,11 @@ function downloadWebTorrentVideo (target: { magnetUri: string, torrentName: stri
           if (err) return rej(err)
 
           if (target.torrentName) {
-            unlinkPromise(torrentId)
+            remove(torrentId)
               .catch(err => logger.error('Cannot remove torrent %s in webtorrent download.', torrentId, { err }))
           }
 
-          unlinkPromise(join(CONFIG.STORAGE.VIDEOS_DIR, file.name))
+          remove(join(CONFIG.STORAGE.VIDEOS_DIR, file.name))
             .catch(err => logger.error('Cannot remove torrent file %s in webtorrent download.', file.name, { err }))
 
           res(path)
index 1926c40dd6dfeaba9ae48054032c73ed3af44a4e..e319164e481eb3224a82798c54d1cd7957702098 100644 (file)
@@ -1,6 +1,5 @@
 import * as passwordGenerator from 'password-generator'
 import { UserRole } from '../../shared'
-import { mkdirpPromise, rimrafPromise } from '../helpers/core-utils'
 import { logger } from '../helpers/logger'
 import { createApplicationActor, createUserAccountAndChannel } from '../lib/user'
 import { UserModel } from '../models/account/user'
@@ -9,6 +8,7 @@ import { OAuthClientModel } from '../models/oauth/oauth-client'
 import { applicationExist, clientsExist, usersExist } from './checker'
 import { CACHE, CONFIG, LAST_MIGRATION_VERSION } from './constants'
 import { sequelizeTypescript } from './database'
+import { remove, ensureDir } from 'fs-extra'
 
 async function installApplication () {
   try {
@@ -41,7 +41,7 @@ function removeCacheDirectories () {
   // Cache directories
   for (const key of Object.keys(cacheDirectories)) {
     const dir = cacheDirectories[key]
-    tasks.push(rimrafPromise(dir))
+    tasks.push(remove(dir))
   }
 
   return Promise.all(tasks)
@@ -52,16 +52,16 @@ function createDirectoriesIfNotExist () {
   const cacheDirectories = Object.keys(CACHE)
                                  .map(k => CACHE[k].DIRECTORY)
 
-  const tasks: Promise<string>[] = []
+  const tasks: Promise<void>[] = []
   for (const key of Object.keys(storage)) {
     const dir = storage[key]
-    tasks.push(mkdirpPromise(dir))
+    tasks.push(ensureDir(dir))
   }
 
   // Cache directories
   for (const key of Object.keys(cacheDirectories)) {
     const dir = cacheDirectories[key]
-    tasks.push(mkdirpPromise(dir))
+    tasks.push(ensureDir(dir))
   }
 
   return Promise.all(tasks)
index 54ea852b1aadf846f453a4019ace98a953387e55..26a188e5e8f834ac0e05f64a6ebea89cb825768e 100644 (file)
@@ -1,9 +1,8 @@
 import * as Sequelize from 'sequelize'
 import { join } from 'path'
-
-import { readdirPromise, renamePromise } from '../../helpers/core-utils'
 import { CONFIG } from '../../initializers/constants'
 import { getVideoFileResolution } from '../../helpers/ffmpeg-utils'
+import { readdir, rename } from 'fs-extra'
 
 function up (utils: {
   transaction: Sequelize.Transaction,
@@ -14,7 +13,7 @@ function up (utils: {
   const torrentDir = CONFIG.STORAGE.TORRENTS_DIR
   const videoFileDir = CONFIG.STORAGE.VIDEOS_DIR
 
-  return readdirPromise(videoFileDir)
+  return readdir(videoFileDir)
     .then(videoFiles => {
       const tasks: Promise<any>[] = []
       for (const videoFile of videoFiles) {
@@ -31,11 +30,11 @@ function up (utils: {
           .then(height => {
             const oldTorrentName = uuid + '.torrent'
             const newTorrentName = uuid + '-' + height + '.torrent'
-            return renamePromise(join(torrentDir, oldTorrentName), join(torrentDir, newTorrentName)).then(() => height)
+            return rename(join(torrentDir, oldTorrentName), join(torrentDir, newTorrentName)).then(() => height)
           })
           .then(height => {
             const newVideoFileName = uuid + '-' + height + '.' + ext
-            return renamePromise(join(videoFileDir, videoFile), join(videoFileDir, newVideoFileName)).then(() => height)
+            return rename(join(videoFileDir, videoFile), join(videoFileDir, newVideoFileName)).then(() => height)
           })
           .then(height => {
             const query = 'UPDATE "VideoFiles" SET "resolution" = ' + height +
index 539e2bc8fbaeb17a6ba52af3334db7296086fb6e..adc2f9fb370ddd9f15ddbd4838a2b5d6be6cac13 100644 (file)
@@ -1,8 +1,8 @@
 import * as path from 'path'
-import { readdirPromise } from '../helpers/core-utils'
 import { logger } from '../helpers/logger'
 import { LAST_MIGRATION_VERSION } from './constants'
 import { sequelizeTypescript } from './database'
+import { readdir } from 'fs-extra'
 
 async function migrate () {
   const tables = await sequelizeTypescript.getQueryInterface().showAllTables()
@@ -52,7 +52,7 @@ export {
 // ---------------------------------------------------------------------------
 
 async function getMigrationScripts () {
-  const files = await readdirPromise(path.join(__dirname, 'migrations'))
+  const files = await readdir(path.join(__dirname, 'migrations'))
   const filesToMigrate: {
     version: string,
     script: string
index 3e20c5d2adbf5b8852ff1a0f07e73676b260666e..7512f2b9da0b260feff00afad908601003fcf25a 100644 (file)
@@ -1,6 +1,5 @@
 import * as AsyncLRU from 'async-lru'
-import { createWriteStream } from 'fs-extra'
-import { unlinkPromise } from '../../helpers/core-utils'
+import { createWriteStream, remove } from 'fs-extra'
 import { logger } from '../../helpers/logger'
 import { VideoModel } from '../../models/video/video'
 import { fetchRemoteVideoStaticFile } from '../activitypub'
@@ -26,7 +25,7 @@ export abstract class AbstractVideoStaticFileCache <T> {
     })
 
     this.lru.on('evict', (obj: { key: string, value: string }) => {
-      unlinkPromise(obj.value)
+      remove(obj.value)
         .then(() => logger.debug('%s evicted from %s', obj.value, this.constructor.name))
     })
   }
index 72984e7789863505519fa831bf35a39efc6d3ce8..a69e09c32d8df849487d1768b5ed5ac7b9b63152 100644 (file)
@@ -1,12 +1,13 @@
 import * as express from 'express'
 import * as Bluebird from 'bluebird'
 import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/models/i18n/i18n'
-import { CONFIG, EMBED_SIZE, CUSTOM_HTML_TAG_COMMENTS, STATIC_PATHS } from '../initializers'
+import { CONFIG, CUSTOM_HTML_TAG_COMMENTS, EMBED_SIZE, STATIC_PATHS } from '../initializers'
 import { join } from 'path'
-import { escapeHTML, readFileBufferPromise } from '../helpers/core-utils'
+import { escapeHTML } from '../helpers/core-utils'
 import { VideoModel } from '../models/video/video'
 import * as validator from 'validator'
 import { VideoPrivacy } from '../../shared/models/videos'
+import { readFile } from 'fs-extra'
 
 export class ClientHtml {
 
@@ -20,7 +21,7 @@ export class ClientHtml {
     const path = ClientHtml.getIndexPath(req, res, paramLang)
     if (ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path]
 
-    const buffer = await readFileBufferPromise(path)
+    const buffer = await readFile(path)
 
     let html = buffer.toString()
 
index d6984ef92959aaf5c6e3a71034ea0335bd75fd89..ebcb2090cd42a725ab5e10c4da489533186aa778 100644 (file)
@@ -6,7 +6,6 @@ import { VideoImportState } from '../../../../shared/models/videos'
 import { getDurationFromVideoFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils'
 import { extname, join } from 'path'
 import { VideoFileModel } from '../../../models/video/video-file'
-import { renamePromise, statPromise, unlinkPromise } from '../../../helpers/core-utils'
 import { CONFIG, sequelizeTypescript } from '../../../initializers'
 import { doRequestAndSaveToFile } from '../../../helpers/requests'
 import { VideoState } from '../../../../shared'
@@ -15,6 +14,7 @@ import { federateVideoIfNeeded } from '../../activitypub'
 import { VideoModel } from '../../../models/video/video'
 import { downloadWebTorrentVideo } from '../../../helpers/webtorrent'
 import { getSecureTorrentName } from '../../../helpers/utils'
+import { rename, stat } from 'fs-extra'
 
 type VideoImportYoutubeDLPayload = {
   type: 'youtube-dl'
@@ -114,7 +114,7 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
     tempVideoPath = await downloader()
 
     // Get information about this video
-    const stats = await statPromise(tempVideoPath)
+    const stats = await stat(tempVideoPath)
     const isAble = await videoImport.User.isAbleToUploadVideo({ size: stats.size })
     if (isAble === false) {
       throw new Error('The user video quota is exceeded with this video to import.')
@@ -138,7 +138,7 @@ async function processFile (downloader: () => Promise<string>, videoImport: Vide
 
     // Move file
     videoDestFile = join(CONFIG.STORAGE.VIDEOS_DIR, videoImport.Video.getVideoFilename(videoFile))
-    await renamePromise(tempVideoPath, videoDestFile)
+    await rename(tempVideoPath, videoDestFile)
     tempVideoPath = null // This path is not used anymore
 
     // Process thumbnail
index da47378e845ee54d2ac73ca5bace9cd86699069a..faadb4334116c0f1429f80824e8b2838512007f2 100644 (file)
@@ -5,9 +5,9 @@ import { AbstractScheduler } from './abstract-scheduler'
 import { SCHEDULER_INTERVALS_MS } from '../../initializers'
 import { logger } from '../../helpers/logger'
 import * as request from 'request'
-import { createWriteStream, writeFile } from 'fs-extra'
+import { createWriteStream, ensureDir, writeFile } from 'fs-extra'
 import { join } from 'path'
-import { mkdirpPromise, root } from '../../helpers/core-utils'
+import { root } from '../../helpers/core-utils'
 
 export class YoutubeDlUpdateScheduler extends AbstractScheduler {
 
@@ -27,7 +27,7 @@ export class YoutubeDlUpdateScheduler extends AbstractScheduler {
     const detailsPath = join(binDirectory, 'details')
     const url = 'https://yt-dl.org/downloads/latest/youtube-dl'
 
-    await mkdirpPromise(binDirectory)
+    await ensureDir(binDirectory)
 
     return new Promise(res => {
       request.get(url, { followRedirect: false }, (err, result) => {
index 51e26c87b3a597bcd8b35c91a7273affd1ce7f15..5d73e24fae4078b814d3e92ed6338b8156e36361 100644 (file)
@@ -1,9 +1,9 @@
 import { join } from 'path'
 import { AfterDestroy, AllowNull, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript'
 import { Avatar } from '../../../shared/models/avatars/avatar.model'
-import { unlinkPromise } from '../../helpers/core-utils'
 import { CONFIG, STATIC_PATHS } from '../../initializers'
 import { logger } from '../../helpers/logger'
+import { remove } from 'fs-extra'
 
 @Table({
   tableName: 'avatar'
@@ -40,6 +40,6 @@ export class AvatarModel extends Model<AvatarModel> {
 
   removeAvatar () {
     const avatarPath = join(CONFIG.STORAGE.AVATARS_DIR, this.filename)
-    return unlinkPromise(avatarPath)
+    return remove(avatarPath)
   }
 }
index 3593646a2ca1a857ed45ad355aee1a5ea9b1f4c6..10ef46c14ebac2cd87a599fc106e11013413ae9e 100644 (file)
@@ -19,7 +19,7 @@ import { VideoCaption } from '../../../shared/models/videos/caption/video-captio
 import { CONFIG, STATIC_PATHS, VIDEO_LANGUAGES } from '../../initializers'
 import { join } from 'path'
 import { logger } from '../../helpers/logger'
-import { unlinkPromise } from '../../helpers/core-utils'
+import { remove } from 'fs-extra'
 
 export enum ScopeNames {
   WITH_VIDEO_UUID_AND_REMOTE = 'WITH_VIDEO_UUID_AND_REMOTE'
@@ -172,6 +172,6 @@ export class VideoCaptionModel extends Model<VideoCaptionModel> {
   }
 
   removeCaptionFile () {
-    return unlinkPromise(CONFIG.STORAGE.CAPTIONS_DIR + this.getCaptionName())
+    return remove(CONFIG.STORAGE.CAPTIONS_DIR + this.getCaptionName())
   }
 }
index a956da16e4b78580ea64096a7e83daa65182ff8b..6271db1b3bf4f537cf6a3f58b854772da5252b7c 100644 (file)
@@ -30,15 +30,7 @@ import { VideoPrivacy, VideoResolution, VideoState } from '../../../shared'
 import { VideoTorrentObject } from '../../../shared/models/activitypub/objects'
 import { Video, VideoDetails, VideoFile } from '../../../shared/models/videos'
 import { VideoFilter } from '../../../shared/models/videos/video-query.type'
-import {
-  copyFilePromise,
-  createTorrentPromise,
-  peertubeTruncate,
-  renamePromise,
-  statPromise,
-  unlinkPromise,
-  writeFilePromise
-} from '../../helpers/core-utils'
+import { createTorrentPromise, peertubeTruncate } from '../../helpers/core-utils'
 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
 import { isBooleanValid } from '../../helpers/custom-validators/misc'
 import {
@@ -95,6 +87,7 @@ import { VideoTagModel } from './video-tag'
 import { ScheduleVideoUpdateModel } from './schedule-video-update'
 import { VideoCaptionModel } from './video-caption'
 import { VideoBlacklistModel } from './video-blacklist'
+import { copy, remove, rename, stat, writeFile } from 'fs-extra'
 
 // FIXME: Define indexes here because there is an issue with TS and Sequelize.literal when called directly in the annotation
 const indexes: Sequelize.DefineIndexesOptions[] = [
@@ -1187,7 +1180,7 @@ export class VideoModel extends Model<VideoModel> {
     const filePath = join(CONFIG.STORAGE.TORRENTS_DIR, this.getTorrentFileName(videoFile))
     logger.info('Creating torrent %s.', filePath)
 
-    await writeFilePromise(filePath, torrent)
+    await writeFile(filePath, torrent)
 
     const parsedTorrent = parseTorrent(torrent)
     videoFile.infoHash = parsedTorrent.infoHash
@@ -1497,14 +1490,14 @@ export class VideoModel extends Model<VideoModel> {
     await transcode(transcodeOptions)
 
     try {
-      await unlinkPromise(videoInputPath)
+      await remove(videoInputPath)
 
       // Important to do this before getVideoFilename() to take in account the new file extension
       inputVideoFile.set('extname', newExtname)
 
       const videoOutputPath = this.getVideoFilePath(inputVideoFile)
-      await renamePromise(videoTranscodedPath, videoOutputPath)
-      const stats = await statPromise(videoOutputPath)
+      await rename(videoTranscodedPath, videoOutputPath)
+      const stats = await stat(videoOutputPath)
       const fps = await getVideoFileFPS(videoOutputPath)
 
       inputVideoFile.set('size', stats.size)
@@ -1545,7 +1538,7 @@ export class VideoModel extends Model<VideoModel> {
 
     await transcode(transcodeOptions)
 
-    const stats = await statPromise(videoOutputPath)
+    const stats = await stat(videoOutputPath)
     const fps = await getVideoFileFPS(videoOutputPath)
 
     newVideoFile.set('size', stats.size)
@@ -1560,7 +1553,7 @@ export class VideoModel extends Model<VideoModel> {
 
   async importVideoFile (inputFilePath: string) {
     const { videoFileResolution } = await getVideoFileResolution(inputFilePath)
-    const { size } = await statPromise(inputFilePath)
+    const { size } = await stat(inputFilePath)
     const fps = await getVideoFileFPS(inputFilePath)
 
     let updatedVideoFile = new VideoFileModel({
@@ -1589,7 +1582,7 @@ export class VideoModel extends Model<VideoModel> {
     }
 
     const outputPath = this.getVideoFilePath(updatedVideoFile)
-    await copyFilePromise(inputFilePath, outputPath)
+    await copy(inputFilePath, outputPath)
 
     await this.createTorrentAndSetInfoHash(updatedVideoFile)
 
@@ -1610,25 +1603,25 @@ export class VideoModel extends Model<VideoModel> {
 
   removeThumbnail () {
     const thumbnailPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName())
-    return unlinkPromise(thumbnailPath)
+    return remove(thumbnailPath)
       .catch(err => logger.warn('Cannot delete thumbnail %s.', thumbnailPath, { err }))
   }
 
   removePreview () {
     const previewPath = join(CONFIG.STORAGE.PREVIEWS_DIR + this.getPreviewName())
-    return unlinkPromise(previewPath)
+    return remove(previewPath)
       .catch(err => logger.warn('Cannot delete preview %s.', previewPath, { err }))
   }
 
   removeFile (videoFile: VideoFileModel) {
     const filePath = join(CONFIG.STORAGE.VIDEOS_DIR, this.getVideoFilename(videoFile))
-    return unlinkPromise(filePath)
+    return remove(filePath)
       .catch(err => logger.warn('Cannot delete file %s.', filePath, { err }))
   }
 
   removeTorrent (videoFile: VideoFileModel) {
     const torrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, this.getTorrentFileName(videoFile))
-    return unlinkPromise(torrentPath)
+    return remove(torrentPath)
       .catch(err => logger.warn('Cannot delete torrent %s.', torrentPath, { err }))
   }
 
index 90450a0bbad0504527c8718ef7aa9884f238f65c..72c9bf9a01b319ae0e0e5f815521a441810b7850 100644 (file)
@@ -13,7 +13,6 @@ import {
   setAccessTokensToServers,
   uploadVideo
 } from '../utils'
-import { join } from 'path'
 import * as libxmljs from 'libxmljs'
 import { addVideoCommentThread } from '../utils/videos/video-comments'
 import { waitJobs } from '../utils/server/jobs'
index ffd23a1adeb257371194e7d7a402908bf8ee1c64..fb480b7043e00847bfc5fb45e47143a825ecc2ca 100644 (file)
@@ -1,5 +1,4 @@
 import * as request from 'supertest'
-import { readFileBufferPromise } from '../../../helpers/core-utils'
 
 type FeedType = 'videos' | 'video-comments'
 
index b0667491bdf0fadc740886e7112ba6ffc64fd5ce..b2f80e9b13fc9470b4d9ac3e7f2eba9ac1f71bfa 100644 (file)
@@ -4,7 +4,7 @@ import * as chai from 'chai'
 import { isAbsolute, join } from 'path'
 import * as request from 'supertest'
 import * as WebTorrent from 'webtorrent'
-import { readFileBufferPromise } from '../../../helpers/core-utils'
+import { readFile } from 'fs-extra'
 
 const expect = chai.expect
 let webtorrent = new WebTorrent()
@@ -43,7 +43,7 @@ async function testImage (url: string, imageName: string, imagePath: string, ext
 
   const body = res.body
 
-  const data = await readFileBufferPromise(join(__dirname, '..', '..', 'fixtures', imageName + extension))
+  const data = await readFile(join(__dirname, '..', '..', 'fixtures', imageName + extension))
   const minLength = body.length - ((20 * body.length) / 100)
   const maxLength = body.length + ((20 * body.length) / 100)
 
index 024a315c72f40d0e246adb28902882def2a65af9..f82b8d90699cd6462c4784b3c8a59ee9ce634efb 100644 (file)
@@ -1,10 +1,9 @@
 /* tslint:disable:no-unused-expression */
 
 import { expect } from 'chai'
-import { existsSync } from 'fs-extra'
+import { existsSync, readdir } from 'fs-extra'
 import { join } from 'path'
 import { Account } from '../../../../shared/models/actors'
-import { readdirPromise } from '../../../helpers/core-utils'
 import { root } from '../index'
 import { makeGetRequest } from '../requests/requests'
 
@@ -47,7 +46,7 @@ async function checkActorFilesWereRemoved (actorUUID: string, serverNumber: numb
     const directoryExists = existsSync(directoryPath)
     expect(directoryExists).to.be.true
 
-    const files = await readdirPromise(directoryPath)
+    const files = await readdir(directoryPath)
     for (const file of files) {
       expect(file).to.not.contain(actorUUID)
     }
index 973bbbe87f0f1163d6c6f68b9aab93441ba2298b..7eee254026452e47042cc12c8ed236f2a17aa6fb 100644 (file)
@@ -1,13 +1,14 @@
 /* tslint:disable:no-unused-expression */
 
 import { expect } from 'chai'
-import { existsSync, readFile } from 'fs-extra'
+import { existsSync, readdir, readFile } from 'fs-extra'
 import * as parseTorrent from 'parse-torrent'
 import { extname, join } from 'path'
 import * as request from 'supertest'
 import {
   buildAbsoluteFixturePath,
-  getMyUserInformation, immutableAssign,
+  getMyUserInformation,
+  immutableAssign,
   makeGetRequest,
   makePutBodyRequest,
   makeUploadRequest,
@@ -16,7 +17,6 @@ import {
   testImage
 } from '../'
 import { VideoDetails, VideoPrivacy } from '../../../../shared/models/videos'
-import { readdirPromise } from '../../../helpers/core-utils'
 import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../../initializers'
 import { dateIsValid, webtorrentAdd } from '../index'
 
@@ -276,7 +276,7 @@ async function checkVideoFilesWereRemoved (videoUUID: string, serverNumber: numb
     const directoryExists = existsSync(directoryPath)
     expect(directoryExists).to.be.true
 
-    const files = await readdirPromise(directoryPath)
+    const files = await readdir(directoryPath)
     for (const file of files) {
       expect(file).to.not.contain(videoUUID)
     }
index e49fbb2f5ef3e0f2253703e0b94fb9581ecc3572..812600f8bb544cb2ba329e4fcac47d0b7c397b2a 100644 (file)
@@ -5,12 +5,12 @@ import * as program from 'commander'
 import { join } from 'path'
 import * as youtubeDL from 'youtube-dl'
 import { VideoPrivacy } from '../../shared/models/videos'
-import { unlinkPromise } from '../helpers/core-utils'
 import { doRequestAndSaveToFile } from '../helpers/requests'
 import { CONSTRAINTS_FIELDS } from '../initializers'
 import { getClient, getVideoCategories, login, searchVideo, uploadVideo } from '../tests/utils'
 import { truncate } from 'lodash'
 import * as prompt from 'prompt'
+import { remove } from 'fs-extra'
 
 program
   .option('-u, --url <url>', 'Server url')
@@ -204,10 +204,8 @@ async function uploadVideoOnPeerTube (videoInfo: any, videoPath: string, languag
     }
   }
 
-  await unlinkPromise(videoPath)
-  if (thumbnailfile) {
-    await unlinkPromise(thumbnailfile)
-  }
+  await remove(videoPath)
+  if (thumbnailfile) await remove(thumbnailfile)
 
   console.log('Uploaded video "%s"!\n', videoAttributes.name)
 }
index b5630bb9cb3be5c3b0ce915c2d6d384b6a418b98..796a0f723aeea127f12de3e18ccb91d1b593a2bf 100644 (file)
@@ -1,13 +1,10 @@
 import * as program from 'commander'
 import { access, constants } from 'fs-extra'
 import { isAbsolute } from 'path'
-import { promisify } from 'util'
 import { getClient, login } from '../tests/utils'
 import { uploadVideo } from '../tests/utils/index'
 import { VideoPrivacy } from '../../shared/models/videos'
 
-const accessPromise = promisify(access)
-
 program
   .option('-u, --url <url>', 'Server url')
   .option('-U, --username <username>', 'Username')
@@ -68,7 +65,7 @@ async function run () {
   const res2 = await login(program[ 'url' ], client, user)
   const accessToken = res2.body.access_token
 
-  await accessPromise(program[ 'file' ], constants.F_OK)
+  await access(program[ 'file' ], constants.F_OK)
 
   console.log('Uploading %s video...', program[ 'videoName' ])
 
index c1a3d6e8846557a589aa4d16ce831c1b5350b58c..b0e1d49f70243f51b62750937ed4cb8f16640f78 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
   dependencies:
     "@types/node" "*"
 
+"@types/fs-extra@^5.0.4":
+  version "5.0.4"
+  resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.0.4.tgz#b971134d162cc0497d221adde3dbb67502225599"
+  dependencies:
+    "@types/node" "*"
+
 "@types/geojson@^1.0.0":
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.6.tgz#3e02972728c69248c2af08d60a48cbb8680fffdf"
@@ -2702,6 +2708,14 @@ fs-extra@^3.0.1:
     jsonfile "^3.0.0"
     universalify "^0.1.0"
 
+fs-extra@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6"
+  dependencies:
+    graceful-fs "^4.1.2"
+    jsonfile "^4.0.0"
+    universalify "^0.1.0"
+
 fs-minipass@^1.2.5:
   version "1.2.5"
   resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d"
@@ -3976,6 +3990,12 @@ jsonfile@^3.0.0:
   optionalDependencies:
     graceful-fs "^4.1.6"
 
+jsonfile@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+  optionalDependencies:
+    graceful-fs "^4.1.6"
+
 jsonify@~0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
@@ -6197,7 +6217,7 @@ right-align@^0.1.1:
   dependencies:
     align-text "^0.1.1"
 
-rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.4.2, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@~2.6.2:
+rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.4.2, rimraf@^2.5.1, rimraf@^2.6.1, rimraf@~2.6.2:
   version "2.6.2"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
   dependencies: