From e3cddbdb7cc4ff74369ab34ec317a83b666060b3 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Mon, 11 May 2020 15:22:56 +0200 Subject: [PATCH 1/7] Promises => async-await Result of running https://github.com/sgilroy/async-await-codemod --- Gruntfile.js | 58 +- components/app/app.js | 7 +- components/branches/branches.js | 16 +- components/graph/git-graph-actions.js | 39 +- components/graph/git-ref.js | 83 +-- components/path/path.js | 49 +- components/remotes/remotes.js | 53 +- components/repository/repository.js | 108 ++-- components/submodules/submodules.js | 17 +- components/textdiff/textdiff.js | 129 ++-- source/git-api.js | 85 ++- source/git-promise.js | 679 ++++++++++---------- source/server.js | 141 ++-- source/ungit-plugin.js | 28 +- source/utils/cache.js | 13 +- test/common-es6.js | 28 +- test/spec.cache.js | 74 +-- test/spec.git-api.branching.js | 222 +++---- test/spec.git-api.conflict-no-auto-stash.js | 54 +- test/spec.git-api.conflict.js | 381 ++++++----- test/spec.git-api.diff.js | 211 +++--- test/spec.git-api.discardchanges.js | 161 +++-- test/spec.git-api.ignorefile.js | 110 ++-- test/spec.git-api.js | 359 +++++------ test/spec.git-api.patch.js | 26 +- test/spec.git-api.remote.js | 121 ++-- test/spec.git-api.squash.js | 75 ++- test/spec.git-api.stash.js | 24 +- test/spec.git-api.submodule.js | 116 ++-- 29 files changed, 1695 insertions(+), 1772 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index d310fd7e7..b4f3a46dd 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -258,20 +258,19 @@ module.exports = (grunt) => { ).then(this.async()); }); - const bumpDependency = (packageJson, packageName) => { + const bumpDependency = async (packageJson, packageName) => { const dependencyType = packageJson['dependencies'][packageName] ? 'dependencies' : 'devDependencies'; let currentVersion = packageJson[dependencyType][packageName]; if (currentVersion[0] == '~' || currentVersion[0] == '^') currentVersion = currentVersion.slice(1); - return pkgVersions(packageName).then((versionSet) => { - const versions = Array.from(versionSet); - const latestVersion = semver.maxSatisfying(versions, '*'); - if (semver.gt(latestVersion, currentVersion)) { - packageJson[dependencyType][packageName] = '~' + latestVersion; - } - }); + const versionSet = await pkgVersions(packageName); + const versions = Array.from(versionSet); + const latestVersion = semver.maxSatisfying(versions, '*'); + if (semver.gt(latestVersion, currentVersion)) { + packageJson[dependencyType][packageName] = '~' + latestVersion; + } }; grunt.registerTask( @@ -332,32 +331,33 @@ module.exports = (grunt) => { .then((tests) => { grunt.log.writeln('Running click tests in parallel... (this will take a while...)'); return Promise.all( - tests.map((file) => { + tests.map(async (file) => { let output = ''; const outStream = (data) => (output += data); grunt.log.writeln(cliColor.set(`Clicktest started! \t${file}`, 'blue')); - return new Promise((resolve, reject) => { - const child = childProcess.execFile( - './node_modules/mocha/bin/mocha', - [path.join(__dirname, 'clicktests', file), '--timeout=35000', '-b'], - { maxBuffer: 10 * 1024 * 1024 } - ); - child.stdout.on('data', outStream); - child.stderr.on('data', outStream); - child.on('exit', (code) => { - if (code == 0) resolve(file); - else reject(); - }); - }) - .then(() => { - grunt.log.writeln(cliColor.set(`'Clicktest success! \t${file}`, 'green')); - return { name: file, output: output, isSuccess: true }; - }) - .catch(() => { - grunt.log.writeln(cliColor.set(`'Clicktest fail! \t'${file}`, 'red')); - return { name: file, output: output, isSuccess: false }; + + try { + await new Promise((resolve, reject) => { + const child = childProcess.execFile( + './node_modules/mocha/bin/mocha', + [path.join(__dirname, 'clicktests', file), '--timeout=35000', '-b'], + { maxBuffer: 10 * 1024 * 1024 } + ); + child.stdout.on('data', outStream); + child.stderr.on('data', outStream); + child.on('exit', (code) => { + if (code == 0) resolve(file); + else reject(); + }); }); + + grunt.log.writeln(cliColor.set(`'Clicktest success! \t${file}`, 'green')); + return { name: file, output: output, isSuccess: true }; + } catch (error) { + grunt.log.writeln(cliColor.set(`'Clicktest fail! \t'${file}`, 'red')); + return { name: file, output: output, isSuccess: false }; + } }) ); }) diff --git a/components/app/app.js b/components/app/app.js index 861f2b92e..006e55009 100644 --- a/components/app/app.js +++ b/components/app/app.js @@ -133,11 +133,10 @@ class AppViewModel { ); } gitSetUserConfig(bugTracking) { - this.server.getPromise('/userconfig').then((userConfig) => { + this.server.getPromise('/userconfig').then(async (userConfig) => { userConfig.bugtracking = bugTracking; - return this.server.postPromise('/userconfig', userConfig).then(() => { - this.bugtrackingEnabled(bugTracking); - }); + await this.server.postPromise('/userconfig', userConfig); + this.bugtrackingEnabled(bugTracking); }); } enableBugtracking() { diff --git a/components/branches/branches.js b/components/branches/branches.js index 8603751f6..53dbdf254 100644 --- a/components/branches/branches.js +++ b/components/branches/branches.js @@ -129,17 +129,21 @@ class BranchesViewModel { details: 'Deleting ' + details + ' branch cannot be undone with ungit.', }) .show() - .closeThen((diag) => { + .closeThen(async (diag) => { if (!diag.result()) return; const url = `${branch.isRemote ? '/remote' : ''}/branches`; - return this.server - .delPromise(url, { + + try { + await this.server.delPromise(url, { path: this.graph.repoPath(), remote: branch.isRemote ? branch.remote : null, name: branch.refName, - }) - .then(() => programEvents.dispatch({ event: 'working-tree-changed' })) - .catch((e) => this.server.unhandledRejection(e)); + }); + + return programEvents.dispatch({ event: 'working-tree-changed' }); + } catch (e) { + return this.server.unhandledRejection(e); + } }); } } diff --git a/components/graph/git-graph-actions.js b/components/graph/git-graph-actions.js index dc8aba6fe..f40a0244c 100644 --- a/components/graph/git-graph-actions.js +++ b/components/graph/git-graph-actions.js @@ -117,13 +117,16 @@ class Reset extends ActionBase { details: 'Resetting to ref: ' + remoteRef.name + ' cannot be undone with ungit.', }) .show() - .closeThen((diag) => { + .closeThen(async (diag) => { if (!diag.result()) return; - return this.server - .postPromise('/reset', { path: this.graph.repoPath(), to: remoteRef.name, mode: 'hard' }) - .then(() => { - context.node(remoteRef.node()); - }); + + await this.server.postPromise('/reset', { + path: this.graph.repoPath(), + to: remoteRef.name, + mode: 'hard', + }); + + context.node(remoteRef.node()); }).closePromise; } } @@ -316,17 +319,19 @@ class Uncommit extends ActionBase { }); } - perform() { - return this.server - .postPromise('/reset', { path: this.graph.repoPath(), to: 'HEAD^', mode: 'mixed' }) - .then(() => { - let targetNode = this.node.belowNode; - while (targetNode && !targetNode.ancestorOfHEAD()) { - targetNode = targetNode.belowNode; - } - this.graph.HEADref().node(targetNode ? targetNode : null); - this.graph.checkedOutRef().node(targetNode ? targetNode : null); - }); + async perform() { + await this.server.postPromise('/reset', { + path: this.graph.repoPath(), + to: 'HEAD^', + mode: 'mixed', + }); + + let targetNode = this.node.belowNode; + while (targetNode && !targetNode.ancestorOfHEAD()) { + targetNode = targetNode.belowNode; + } + this.graph.HEADref().node(targetNode ? targetNode : null); + this.graph.checkedOutRef().node(targetNode ? targetNode : null); } } diff --git a/components/graph/git-ref.js b/components/graph/git-ref.js index 8530800b0..cee9e196f 100644 --- a/components/graph/git-ref.js +++ b/components/graph/git-ref.js @@ -99,7 +99,7 @@ class RefViewModel extends Selectable { this.isDragging(false); } - moveTo(target, rewindWarnOverride) { + async moveTo(target, rewindWarnOverride) { let promise; if (this.isLocal) { const toNode = this.graph.nodesById[target]; @@ -161,16 +161,17 @@ class RefViewModel extends Selectable { }); } - return promise - .then((res) => { - if (!res) return; - const targetNode = this.graph.getNode(target); - if (this.graph.checkedOutBranch() == this.refName) { - this.graph.HEADref().node(targetNode); - } - this.node(targetNode); - }) - .catch((e) => this.server.unhandledRejection(e)); + try { + const res = await promise; + if (!res) return; + const targetNode = this.graph.getNode(target); + if (this.graph.checkedOutBranch() == this.refName) { + this.graph.HEADref().node(targetNode); + } + this.node(targetNode); + } catch (e) { + return this.server.unhandledRejection(e); + } } remove(isClientOnly) { @@ -241,39 +242,39 @@ class RefViewModel extends Selectable { .catch((e) => this.server.unhandledRejection(e)); } - checkout() { + async checkout() { const isRemote = this.isRemoteBranch; const isLocalCurrent = this.getLocalRef() && this.getLocalRef().current(); - return Promise.resolve() - .then(() => { - if (isRemote && !isLocalCurrent) { - return this.server.postPromise('/branches', { - path: this.graph.repoPath(), - name: this.refName, - sha1: this.name, - force: true, - }); - } - }) - .then(() => - this.server.postPromise('/checkout', { path: this.graph.repoPath(), name: this.refName }) - ) - .then(() => { - if (isRemote && isLocalCurrent) { - return this.server.postPromise('/reset', { - path: this.graph.repoPath(), - to: this.name, - mode: 'hard', - }); - } - }) - .then(() => { - this.graph.HEADref().node(this.node()); - }) - .catch((err) => { - if (err.errorCode != 'merge-failed') this.server.unhandledRejection(err); - }); + try { + await Promise.resolve() + .then(() => { + if (isRemote && !isLocalCurrent) { + return this.server.postPromise('/branches', { + path: this.graph.repoPath(), + name: this.refName, + sha1: this.name, + force: true, + }); + } + }) + .then(() => + this.server.postPromise('/checkout', { path: this.graph.repoPath(), name: this.refName }) + ) + .then(() => { + if (isRemote && isLocalCurrent) { + return this.server.postPromise('/reset', { + path: this.graph.repoPath(), + to: this.name, + mode: 'hard', + }); + } + }); + + this.graph.HEADref().node(this.node()); + } catch (err) { + if (err.errorCode != 'merge-failed') this.server.unhandledRejection(err); + } } } diff --git a/components/path/path.js b/components/path/path.js index 3948979be..ae3c8ec06 100644 --- a/components/path/path.js +++ b/components/path/path.js @@ -43,27 +43,26 @@ class PathViewModel { updateAnimationFrame(deltaT) { if (this.repository()) this.repository().updateAnimationFrame(deltaT); } - updateStatus() { - return this.server - .getPromise('/quickstatus', { path: this.repoPath() }) - .then((status) => { - if (status.type == 'inited' || status.type == 'bare') { - if (this.repoPath() !== status.gitRootPath) { - this.repoPath(status.gitRootPath); - programEvents.dispatch({ event: 'navigated-to-path', path: this.repoPath() }); - programEvents.dispatch({ event: 'working-tree-changed' }); - } - this.status(status.type); - if (!this.repository()) { - this.repository(components.create('repository', { server: this.server, path: this })); - } - } else if (status.type == 'uninited' || status.type == 'no-such-path') { - this.status(status.type); - this.repository(null); + async updateStatus() { + try { + const status = await this.server.getPromise('/quickstatus', { path: this.repoPath() }); + + if (status.type == 'inited' || status.type == 'bare') { + if (this.repoPath() !== status.gitRootPath) { + this.repoPath(status.gitRootPath); + programEvents.dispatch({ event: 'navigated-to-path', path: this.repoPath() }); + programEvents.dispatch({ event: 'working-tree-changed' }); } - return null; - }) - .catch((err) => {}); + this.status(status.type); + if (!this.repository()) { + this.repository(components.create('repository', { server: this.server, path: this })); + } + } else if (status.type == 'uninited' || status.type == 'no-such-path') { + this.status(status.type); + this.repository(null); + } + return null; + } catch (err) {} } initRepository() { return this.server @@ -96,11 +95,13 @@ class PathViewModel { programEvents.dispatch({ event: 'working-tree-changed' }); }); } - createDir() { + async createDir() { this.showDirectoryCreatedAlert(true); - return this.server + + await this.server .postPromise('/createDir', { dir: this.repoPath() }) - .catch((e) => this.server.unhandledRejection(e)) - .then(() => this.updateStatus()); + .catch((e) => this.server.unhandledRejection(e)); + + return this.updateStatus(); } } diff --git a/components/remotes/remotes.js b/components/remotes/remotes.js index b5b49be45..9a23df8d9 100644 --- a/components/remotes/remotes.js +++ b/components/remotes/remotes.js @@ -113,35 +113,34 @@ class RemotesViewModel { }); } - updateRemotes() { - return this.server - .getPromise('/remotes', { path: this.repoPath() }) - .then((remotes) => { - remotes = remotes.map((remote) => ({ - name: remote, - changeRemote: () => { - this.currentRemote(remote); - }, - })); - this.remotes(remotes); - if (!this.currentRemote() && remotes.length > 0) { - if (_.find(remotes, { name: 'origin' })) { - // default to origin if it exists - this.currentRemote('origin'); - } else { - // otherwise take the first one - this.currentRemote(remotes[0].name); - } + async updateRemotes() { + try { + let remotes = await this.server.getPromise('/remotes', { path: this.repoPath() }); - if (this.shouldAutoFetch) { - this.shouldAutoFetch = false; - return this.fetch({ nodes: true, tags: true }); - } + remotes = remotes.map((remote) => ({ + name: remote, + changeRemote: () => { + this.currentRemote(remote); + }, + })); + this.remotes(remotes); + if (!this.currentRemote() && remotes.length > 0) { + if (_.find(remotes, { name: 'origin' })) { + // default to origin if it exists + this.currentRemote('origin'); + } else { + // otherwise take the first one + this.currentRemote(remotes[0].name); } - }) - .catch((err) => { - if (err.errorCode != 'not-a-repository') this.server.unhandledRejection(err); - }); + + if (this.shouldAutoFetch) { + this.shouldAutoFetch = false; + return this.fetch({ nodes: true, tags: true }); + } + } + } catch (err) { + if (err.errorCode != 'not-a-repository') this.server.unhandledRejection(err); + } } showAddRemoteDialog() { diff --git a/components/repository/repository.js b/components/repository/repository.js index c30704302..6cd4abe0e 100644 --- a/components/repository/repository.js +++ b/components/repository/repository.js @@ -64,66 +64,64 @@ class RepositoryViewModel { if (this.graph.updateAnimationFrame) this.graph.updateAnimationFrame(deltaT); } - refreshSubmoduleStatus() { - return this.server - .getPromise('/baserepopath', { path: this.repoPath() }) - .then((baseRepoPath) => { - if (baseRepoPath.path) { - return this.server - .getProimse('/submodules', { path: baseRepoPath.path }) - .then((submodules) => { - if (Array.isArray(submodules)) { - const baseName = this.repoPath().substring(baseRepoPath.path.length + 1); - for (let n = 0; n < submodules.length; n++) { - if (submodules[n].path === baseName) { - this.parentModulePath(baseRepoPath.path); - this.parentModuleLink( - `/#/repository?path=${encodeURIComponent(baseRepoPath.path)}` - ); - return; - } + async refreshSubmoduleStatus() { + try { + const baseRepoPath = await this.server.getPromise('/baserepopath', { path: this.repoPath() }); + + if (baseRepoPath.path) { + return this.server + .getProimse('/submodules', { path: baseRepoPath.path }) + .then((submodules) => { + if (Array.isArray(submodules)) { + const baseName = this.repoPath().substring(baseRepoPath.path.length + 1); + for (let n = 0; n < submodules.length; n++) { + if (submodules[n].path === baseName) { + this.parentModulePath(baseRepoPath.path); + this.parentModuleLink( + `/#/repository?path=${encodeURIComponent(baseRepoPath.path)}` + ); + return; } } - }); - } - }) - .catch((err) => { - this.parentModuleLink(undefined); - this.parentModulePath(undefined); - }); - } - - editGitignore() { - return this.server - .getPromise('/gitignore', { path: this.repoPath() }) - .then((res) => { - return components - .create('texteditdialog', { - title: `${this.repoPath()}${ungit.config.fileSeparator}.gitignore`, - content: res.content, - }) - .show() - .closeThen((diag) => { - if (diag.result()) { - return this.server.putPromise('/gitignore', { - path: this.repoPath(), - data: diag.textAreaContent, - }); } }); - }) - .catch((e) => { - // Not a git error but we are going to treat like one - programEvents.dispatch({ - event: 'git-error', - data: { - command: `fs.write "${this.repoPath()}${ungit.config.fileSeparator}.gitignore"`, - error: e.message || e.errorSummary, - stdout: '', - stderr: e.stack, - repoPath: this.repoPath(), - }, + } + } catch (err) { + this.parentModuleLink(undefined); + this.parentModulePath(undefined); + } + } + + async editGitignore() { + try { + const res = await this.server.getPromise('/gitignore', { path: this.repoPath() }); + + return components + .create('texteditdialog', { + title: `${this.repoPath()}${ungit.config.fileSeparator}.gitignore`, + content: res.content, + }) + .show() + .closeThen((diag) => { + if (diag.result()) { + return this.server.putPromise('/gitignore', { + path: this.repoPath(), + data: diag.textAreaContent, + }); + } }); + } catch (e) { + // Not a git error but we are going to treat like one + programEvents.dispatch({ + event: 'git-error', + data: { + command: `fs.write "${this.repoPath()}${ungit.config.fileSeparator}.gitignore"`, + error: e.message || e.errorSummary, + stdout: '', + stderr: e.stack, + repoPath: this.repoPath(), + }, }); + } } } diff --git a/components/submodules/submodules.js b/components/submodules/submodules.js index a7081ba88..203e36be4 100644 --- a/components/submodules/submodules.js +++ b/components/submodules/submodules.js @@ -26,14 +26,15 @@ class SubmodulesViewModel { }); } - fetchSubmodules() { - return this.server - .getPromise('/submodules', { path: this.repoPath() }) - .then((submodules) => { - this.submodules(submodules && Array.isArray(submodules) ? submodules : []); - return this; - }) - .catch((e) => this.server.unhandledRejection(e)); + async fetchSubmodules() { + try { + const submodules = await this.server.getPromise('/submodules', { path: this.repoPath() }); + + this.submodules(submodules && Array.isArray(submodules) ? submodules : []); + return this; + } catch (e) { + return this.server.unhandledRejection(e); + } } updateSubmodules() { diff --git a/components/textdiff/textdiff.js b/components/textdiff/textdiff.js index 4bfcea92e..29e743e6d 100644 --- a/components/textdiff/textdiff.js +++ b/components/textdiff/textdiff.js @@ -110,81 +110,78 @@ class TextDiffViewModel { if (this.isShowingDiffs()) this.render(); } - getDiffJson() { - return this.server - .getPromise('/diff', this.getDiffArguments()) - .then((diffs) => { - if (typeof diffs !== 'string') { - // Invalid value means there is no changes, show dummy diff without any changes - diffs = `diff --git a/${this.filename} b/${this.filename} - index aaaaaaaa..bbbbbbbb 111111 - --- a/${this.filename} - +++ b/${this.filename}`; - } - this.diffJson = diff2html.parse(diffs); - }) - .catch((err) => { - // The file existed before but has been removed, but we're trying to get a diff for it - // Most likely it will just disappear with the next refresh of the staging area - // so we just ignore the error here - if (err.errorCode != 'no-such-file') this.server.unhandledRejection(err); - }); + async getDiffJson() { + try { + let diffs = await this.server.getPromise('/diff', this.getDiffArguments()); + + if (typeof diffs !== 'string') { + // Invalid value means there is no changes, show dummy diff without any changes + diffs = `diff --git a/${this.filename} b/${this.filename} + index aaaaaaaa..bbbbbbbb 111111 + --- a/${this.filename} + +++ b/${this.filename}`; + } + this.diffJson = diff2html.parse(diffs); + } catch (err) { + // The file existed before but has been removed, but we're trying to get a diff for it + // Most likely it will just disappear with the next refresh of the staging area + // so we just ignore the error here + if (err.errorCode != 'no-such-file') this.server.unhandledRejection(err); + } } - render() { - return (!this.diffJson ? this.getDiffJson() : Promise.resolve()).then(() => { - if (!this.diffJson || this.diffJson.length == 0) return; // check if diffs are available (binary files do not support them) - - if (!this.diffJson[0].allBlocks) { - this.diffJson[0].allBlocks = this.diffJson[0].blocks; - } + async render() { + (await !this.diffJson) ? this.getDiffJson() : Promise.resolve(); + if (!this.diffJson || this.diffJson.length == 0) return; // check if diffs are available (binary files do not support them) - let currentLoadCount = Math.max(this.loadCount, loadLimit); - let lineCount = 0; - let loadCount = 0; - this.diffJson[0].blocks = this.diffJson[0].allBlocks.reduce((blocks, block) => { - const length = block.lines.length; - const remaining = currentLoadCount - lineCount; - if (remaining > 0) { - loadCount += length; - blocks.push(block); - } - lineCount += length; - return blocks; - }, []); + if (!this.diffJson[0].allBlocks) { + this.diffJson[0].allBlocks = this.diffJson[0].blocks; + } - this.loadCount = loadCount; - this.hasMore(lineCount > loadCount); + let currentLoadCount = Math.max(this.loadCount, loadLimit); + let lineCount = 0; + let loadCount = 0; + this.diffJson[0].blocks = this.diffJson[0].allBlocks.reduce((blocks, block) => { + const length = block.lines.length; + const remaining = currentLoadCount - lineCount; + if (remaining > 0) { + loadCount += length; + blocks.push(block); + } + lineCount += length; + return blocks; + }, []); - let html = diff2html.html(this.diffJson, { - outputFormat: - this.textDiffType.value() === sideBySideDiff ? 'side-by-side' : 'line-by-line', - drawFileList: false, - }); + this.loadCount = loadCount; + this.hasMore(lineCount > loadCount); - this.numberOfSelectedPatchLines = 0; - let index = 0; + let html = diff2html.html(this.diffJson, { + outputFormat: this.textDiffType.value() === sideBySideDiff ? 'side-by-side' : 'line-by-line', + drawFileList: false, + }); - // ko's binding resolution is not recursive, which means below ko.bind refresh method doesn't work for - // data bind at getPatchCheckBox that is rendered with "html" binding. - // which is reason why manually updating the html content and refreshing kobinding to have it render... - if (this.patchLineList) { - html = html.replace(/(\+|\-)/g, (match, capture) => { - if (this.patchLineList()[index] === undefined) { - this.patchLineList()[index] = true; - } + this.numberOfSelectedPatchLines = 0; + let index = 0; + + // ko's binding resolution is not recursive, which means below ko.bind refresh method doesn't work for + // data bind at getPatchCheckBox that is rendered with "html" binding. + // which is reason why manually updating the html content and refreshing kobinding to have it render... + if (this.patchLineList) { + html = html.replace(/(\+|\-)/g, (match, capture) => { + if (this.patchLineList()[index] === undefined) { + this.patchLineList()[index] = true; + } - return this.getPatchCheckBox(capture, index, this.patchLineList()[index++]); - }); - } + return this.getPatchCheckBox(capture, index, this.patchLineList()[index++]); + }); + } - if (html !== this.htmlSrc) { - // diff has changed since last we displayed and need refresh - this.htmlSrc = html; - this.isParsed(false); - this.isParsed(true); - } - }); + if (html !== this.htmlSrc) { + // diff has changed since last we displayed and need refresh + this.htmlSrc = html; + this.isParsed(false); + this.isParsed(true); + } } loadMore() { diff --git a/source/git-api.js b/source/git-api.js index 7d9795580..feaee94c4 100644 --- a/source/git-api.js +++ b/source/git-api.js @@ -60,33 +60,31 @@ exports.registerApi = (env) => { }); } - const watchPath = (socket, subfolderPath, options) => { + const watchPath = async (socket, subfolderPath, options) => { const pathToWatch = path.join(socket.watcherPath, subfolderPath); winston.info(`Start watching ${pathToWatch}`); - return fs - .access(pathToWatch) - .catch(() => { - // Sometimes necessary folders, '.../.git/refs/heads' and etc, are not created on git init - winston.debug(`intended folder to watch doesn't exists, creating: ${pathToWatch}`); - return mkdirp(pathToWatch); - }) - .then(() => { - const watcher = watch(pathToWatch, options || {}); - watcher.on('change', (event, filename) => { - if (!filename) return; - const filePath = path.join(subfolderPath, filename); - winston.debug(`File change: ${filePath}`); - if (isFileWatched(filePath, socket.ignore)) { - winston.info(`${filePath} triggered refresh for ${socket.watcherPath}`); - emitGitDirectoryChanged(socket.watcherPath); - emitWorkingTreeChanged(socket.watcherPath); - } - }); - watcher.on('error', (err) => { - winston.warn(`Error watching ${pathToWatch}: `, JSON.stringify(err)); - }); - socket.watcher.push(watcher); - }); + + await fs.access(pathToWatch).catch(() => { + // Sometimes necessary folders, '.../.git/refs/heads' and etc, are not created on git init + winston.debug(`intended folder to watch doesn't exists, creating: ${pathToWatch}`); + return mkdirp(pathToWatch); + }); + + const watcher = watch(pathToWatch, options || {}); + watcher.on('change', (event, filename) => { + if (!filename) return; + const filePath = path.join(subfolderPath, filename); + winston.debug(`File change: ${filePath}`); + if (isFileWatched(filePath, socket.ignore)) { + winston.info(`${filePath} triggered refresh for ${socket.watcherPath}`); + emitGitDirectoryChanged(socket.watcherPath); + emitWorkingTreeChanged(socket.watcherPath); + } + }); + watcher.on('error', (err) => { + winston.warn(`Error watching ${pathToWatch}: `, JSON.stringify(err)); + }); + socket.watcher.push(watcher); }; const stopDirectoryWatch = (socket) => { @@ -178,15 +176,14 @@ exports.registerApi = (env) => { } }; - const jsonResultOrFailProm = (res, promise) => { - return promise - .then((result) => { - res.json(result || {}); - }) - .catch((err) => { - winston.warn('Responding with ERROR: ', JSON.stringify(err)); - res.status(400).json(err); - }); + const jsonResultOrFailProm = async (res, promise) => { + try { + const result = await promise; + res.json(result || {}); + } catch (err) { + winston.warn('Responding with ERROR: ', JSON.stringify(err)); + res.status(400).json(err); + } }; const credentialsOption = (socketId, remote) => { @@ -448,15 +445,14 @@ exports.registerApi = (env) => { const remotes = remoteText.trim().split('\n'); // making calls serially as credential helpers may get confused to which cred to get. - return remotes.reduce((promise, remote) => { + return remotes.reduce(async (promise, remote) => { if (!remote || remote === '') return promise; - return promise.then(() => { - return gitPromise({ - commands: credentialsOption(req.query.socketId, remote).concat(['fetch', remote]), - repoPath: req.query.path, - timeout: tenMinTimeoutMs, - }).catch((e) => winston.warn('err during remote fetch for /refs', e)); // ignore fetch err as it is most likely credential - }); + await promise; + return gitPromise({ + commands: credentialsOption(req.query.socketId, remote).concat(['fetch', remote]), + repoPath: req.query.path, + timeout: tenMinTimeoutMs, + }).catch((e) => winston.warn('err during remote fetch for /refs', e)); // ignore fetch err as it is most likely credential }, Promise.resolve()); }) .then(() => gitPromise(['show-ref', '-d'], req.query.path)) @@ -816,8 +812,9 @@ exports.registerApi = (env) => { const task = fs .access(filename) - .then(() => { - return fs.readFile(filename, { encoding: 'utf8' }).then(gitParser.parseGitSubmodule); + .then(async () => { + const readFileResult = await fs.readFile(filename, { encoding: 'utf8' }); + return gitParser.parseGitSubmodule(readFileResult); }) .catch(() => { return {}; diff --git a/source/git-promise.js b/source/git-promise.js index 2fe4f87da..ae0bbc9e5 100644 --- a/source/git-promise.js +++ b/source/git-promise.js @@ -45,85 +45,84 @@ const isRetryableError = (err) => { return false; }; -const gitExecutorProm = (args, retryCount) => { - return rateLimiter() - .then(() => { - return new Promise((resolve, reject) => { - if (config.logGitCommands) - winston.info(`git executing: ${args.repoPath} ${args.commands.join(' ')}`); - let rejectedError = null; - let isCompleted = false; - let stdout = ''; - let stderr = ''; - let env = JSON.parse(JSON.stringify(process.env)); - env['LC_ALL'] = 'C'; - const procOpts = { - cwd: args.repoPath, - maxBuffer: 1024 * 1024 * 100, - detached: false, - env: env, - }; - const gitProcess = child_process.spawn(gitBin, args.commands, procOpts); - if (args.timeout) { - setTimeout(() => { - if (isCompleted) return; - isCompleted = true; - winston.warn(`command timedout: ${args.commands.join(' ')}\n`); - gitSem.signal(); - gitProcess.kill('SIGINT'); - }, args.timeout); - } - - if (args.outPipe) { - gitProcess.stdout.pipe(args.outPipe); - } else { - gitProcess.stdout.on('data', (data) => (stdout += data.toString())); - } - if (args.inPipe) { - gitProcess.stdin.end(args.inPipe); - } - gitProcess.stderr.on('data', (data) => (stderr += data.toString())); - gitProcess.on('error', (error) => { - rejectedError = error; - }); - - gitProcess.on('close', (code) => { +const gitExecutorProm = async (args, retryCount) => { + try { + await rateLimiter(); + return new Promise((resolve, reject) => { + if (config.logGitCommands) + winston.info(`git executing: ${args.repoPath} ${args.commands.join(' ')}`); + let rejectedError = null; + let isCompleted = false; + let stdout = ''; + let stderr = ''; + let env = JSON.parse(JSON.stringify(process.env)); + env['LC_ALL'] = 'C'; + const procOpts = { + cwd: args.repoPath, + maxBuffer: 1024 * 1024 * 100, + detached: false, + env: env, + }; + const gitProcess = child_process.spawn(gitBin, args.commands, procOpts); + if (args.timeout) { + setTimeout(() => { if (isCompleted) return; isCompleted = true; - - if (config.logGitCommands) - winston.info( - `git result (first 400 bytes): ${args.commands.join(' ')}\n${stderr.slice( - 0, - 400 - )}\n${stdout.slice(0, 400)}` - ); - if (args.outPipe) args.outPipe.end(); + winston.warn(`command timedout: ${args.commands.join(' ')}\n`); gitSem.signal(); + gitProcess.kill('SIGINT'); + }, args.timeout); + } - if (rejectedError) { - reject(rejectedError); - } else if (code === 0 || (code === 1 && args.allowError)) { - resolve(stdout); - } else { - reject(getGitError(args, stderr, stdout)); - } - }); - }); - }) - .catch((err) => { - if (retryCount > 0 && isRetryableError(err)) { - return new Promise((resolve) => { - winston.warn( - `retrying git commands after lock acquired fail. (If persists, lower 'maxConcurrentGitOperations')` - ); - // sleep random amount between 250 ~ 750 ms - setTimeout(resolve, Math.floor(Math.random() * 500 + 250)); - }).then(gitExecutorProm.bind(null, args, retryCount - 1)); + if (args.outPipe) { + gitProcess.stdout.pipe(args.outPipe); } else { - throw err; + gitProcess.stdout.on('data', (data) => (stdout += data.toString())); } + if (args.inPipe) { + gitProcess.stdin.end(args.inPipe); + } + gitProcess.stderr.on('data', (data) => (stderr += data.toString())); + gitProcess.on('error', (error) => { + rejectedError = error; + }); + + gitProcess.on('close', (code) => { + if (isCompleted) return; + isCompleted = true; + + if (config.logGitCommands) + winston.info( + `git result (first 400 bytes): ${args.commands.join(' ')}\n${stderr.slice( + 0, + 400 + )}\n${stdout.slice(0, 400)}` + ); + if (args.outPipe) args.outPipe.end(); + gitSem.signal(); + + if (rejectedError) { + reject(rejectedError); + } else if (code === 0 || (code === 1 && args.allowError)) { + resolve(stdout); + } else { + reject(getGitError(args, stderr, stdout)); + } + }); }); + } catch (err) { + if (retryCount > 0 && isRetryableError(err)) { + return new Promise((resolve) => { + winston.warn( + `retrying git commands after lock acquired fail. (If persists, lower 'maxConcurrentGitOperations')` + ); + // sleep random amount between 250 ~ 750 ms + setTimeout(resolve, Math.floor(Math.random() * 500 + 250)); + }).then(gitExecutorProm.bind(null, args, retryCount - 1)); + } else { + throw err; + } + } }; /** @@ -226,8 +225,8 @@ const getGitError = (args, stderr, stdout) => { return err; }; -git.status = (repoPath, file) => { - return Promise.all([ +git.status = async (repoPath, file) => { + const result = await Promise.all([ // 0: numStatsStaged git([gitOptionalLocks, 'diff', '--numstat', '--cached', '-z', '--', file || ''], repoPath).then( gitParser.parseGitStatusNumstat @@ -241,8 +240,8 @@ git.status = (repoPath, file) => { // 2: status git([gitOptionalLocks, 'status', '-s', '-b', '-u', '-z', file || ''], repoPath) .then(gitParser.parseGitStatus) - .then((status) => { - return Promise.all([ + .then(async (status) => { + await Promise.all([ // 0: isRebaseMerge fs .access(path.join(repoPath, '.git', 'rebase-merge')) @@ -263,83 +262,80 @@ git.status = (repoPath, file) => { .access(path.join(repoPath, '.git', 'CHERRY_PICK_HEAD')) .then(() => true) .catch(() => false), - ]) - .then((result) => { - status.inRebase = result[0] || result[1]; - status.inMerge = result[2]; - status.inCherry = result[3]; - }) - .then(() => { - if (status.inMerge || status.inCherry) { - return fs - .readFile(path.join(repoPath, '.git', 'MERGE_MSG'), { encoding: 'utf8' }) - .then((commitMessage) => { - status.commitMessage = commitMessage; - return status; - }) - .catch((err) => { - // 'MERGE_MSG' file is gone away, which means we are no longer in merge state - // and state changed while this call is being made. - status.inMerge = status.inCherry = false; - return status; - }); - } - return status; - }); - }), - ]).then((result) => { - const numstats = [result[0], result[1]].reduce(_.extend, {}); - const status = result[2]; - status.inConflict = false; - - // merge numstats - Object.keys(status.files).forEach((filename) => { - // git diff returns paths relative to git repo but git status does not - const absoluteFilename = filename.replace(/\.\.\//g, ''); - const stats = numstats[absoluteFilename] || { additions: '-', deletions: '-' }; - const fileObj = status.files[filename]; - fileObj.additions = stats.additions; - fileObj.deletions = stats.deletions; - if (!status.inConflict && fileObj.conflict) { - status.inConflict = true; - } - }); + ]).then((result) => { + status.inRebase = result[0] || result[1]; + status.inMerge = result[2]; + status.inCherry = result[3]; + }); - return status; + if (status.inMerge || status.inCherry) { + return fs + .readFile(path.join(repoPath, '.git', 'MERGE_MSG'), { encoding: 'utf8' }) + .then((commitMessage) => { + status.commitMessage = commitMessage; + return status; + }) + .catch((err) => { + // 'MERGE_MSG' file is gone away, which means we are no longer in merge state + // and state changed while this call is being made. + status.inMerge = status.inCherry = false; + return status; + }); + } + return status; + }), + ]); + + const numstats = [result[0], result[1]].reduce(_.extend, {}); + const status = result[2]; + status.inConflict = false; + + // merge numstats + Object.keys(status.files).forEach((filename) => { + // git diff returns paths relative to git repo but git status does not + const absoluteFilename = filename.replace(/\.\.\//g, ''); + const stats = numstats[absoluteFilename] || { additions: '-', deletions: '-' }; + const fileObj = status.files[filename]; + fileObj.additions = stats.additions; + fileObj.deletions = stats.deletions; + if (!status.inConflict && fileObj.conflict) { + status.inConflict = true; + } }); + + return status; }; -git.getRemoteAddress = (repoPath, remoteName) => { - return git(['config', '--get', `remote.${remoteName}.url`], repoPath).then((text) => - addressParser.parseAddress(text.split('\n')[0]) - ); +git.getRemoteAddress = async (repoPath, remoteName) => { + const text = await git(['config', '--get', `remote.${remoteName}.url`], repoPath); + return addressParser.parseAddress(text.split('\n')[0]); }; -git.resolveConflicts = (repoPath, files) => { +git.resolveConflicts = async (repoPath, files) => { const toAdd = []; const toRemove = []; - return Promise.all( - (files || []).map((file) => { - return fs - .access(path.join(repoPath, file)) - .then(() => { - toAdd.push(file); - }) - .catch(() => { - toRemove.push(file); - }); + + await Promise.all( + (files || []).map(async (file) => { + try { + await fs.access(path.join(repoPath, file)); + + toAdd.push(file); + } catch (error) { + toRemove.push(file); + } }) - ).then(() => { - const addExec = toAdd.length > 0 ? git(['add', toAdd], repoPath) : null; - const removeExec = toRemove.length > 0 ? git(['rm', toRemove], repoPath) : null; - return Promise.all([addExec, removeExec]); - }); + ); + + const addExec = toAdd.length > 0 ? git(['add', toAdd], repoPath) : null; + const removeExec = toRemove.length > 0 ? git(['rm', toRemove], repoPath) : null; + return Promise.all([addExec, removeExec]); }; -git.stashExecuteAndPop = (commands, repoPath, allowError, outPipe, inPipe, timeout) => { +git.stashExecuteAndPop = async (commands, repoPath, allowError, outPipe, inPipe, timeout) => { let hadLocalChanges = true; - return git(['stash'], repoPath) + await git(['stash'], repoPath) .catch((err) => { if (err.stderr.indexOf('You do not have the initial commit yet') != -1) { hadLocalChanges = err.stderr.indexOf('You do not have the initial commit yet') == -1; @@ -352,17 +348,16 @@ git.stashExecuteAndPop = (commands, repoPath, allowError, outPipe, inPipe, timeo hadLocalChanges = false; } return git(commands, repoPath, allowError, outPipe, inPipe, timeout); - }) - .then(() => { - return hadLocalChanges ? git(['stash', 'pop'], repoPath) : null; }); + + return hadLocalChanges ? git(['stash', 'pop'], repoPath) : null; }; git.binaryFileContent = (repoPath, filename, version, outPipe) => { return git(['show', `${version}:${filename}`], repoPath, null, outPipe); }; -git.diffFile = (repoPath, filename, oldFilename, sha1, ignoreWhiteSpace) => { +git.diffFile = async (repoPath, filename, oldFilename, sha1, ignoreWhiteSpace) => { if (sha1) { return git(['rev-list', '--max-parents=0', sha1], repoPath).then((initialCommitSha1) => { let prevSha1 = sha1 == initialCommitSha1.trim() ? gitEmptyReproSha1 : `${sha1}^`; @@ -385,95 +380,85 @@ git.diffFile = (repoPath, filename, oldFilename, sha1, ignoreWhiteSpace) => { }); } - return git - .revParse(repoPath) - .then((revParse) => { - return revParse.type === 'bare' ? { files: {} } : git.status(repoPath); - }) // if bare do not call status - .then((status) => { - const file = status.files[filename]; - if (!file) { - return fs - .access(path.join(repoPath, filename)) - .then(() => { - return []; - }) - .catch(() => { - throw { error: `No such file: ${filename}`, errorCode: 'no-such-file' }; - }); - // If the file is new or if it's a directory, i.e. a submodule - } else { - if (file && file.isNew) { - return git( - ['diff', '--no-index', isWindows ? 'NUL' : '/dev/null', filename.trim()], - repoPath, - true - ); - } else if (file && file.renamed) { - return git( - ['diff', ignoreWhiteSpace ? '-w' : '', `HEAD:${oldFilename}`, filename.trim()], - repoPath - ); - } else { - return git( - ['diff', ignoreWhiteSpace ? '-w' : '', 'HEAD', '--', filename.trim()], - repoPath - ); - } - } - }); + const status = await // if bare do not call status + git.revParse(repoPath).then((revParse) => { + return revParse.type === 'bare' ? { files: {} } : git.status(repoPath); + }); + + const file = status.files[filename]; + if (!file) { + return fs + .access(path.join(repoPath, filename)) + .then(() => { + return []; + }) + .catch(() => { + throw { error: `No such file: ${filename}`, errorCode: 'no-such-file' }; + }); + // If the file is new or if it's a directory, i.e. a submodule + } else { + if (file && file.isNew) { + return git( + ['diff', '--no-index', isWindows ? 'NUL' : '/dev/null', filename.trim()], + repoPath, + true + ); + } else if (file && file.renamed) { + return git( + ['diff', ignoreWhiteSpace ? '-w' : '', `HEAD:${oldFilename}`, filename.trim()], + repoPath + ); + } else { + return git(['diff', ignoreWhiteSpace ? '-w' : '', 'HEAD', '--', filename.trim()], repoPath); + } + } }; -git.getCurrentBranch = (repoPath) => { - return git(['branch'], repoPath) - .then(gitParser.parseGitBranches) - .then((branches) => { - let branch = branches.find((branch) => branch.current); - if (branch) { - return branch.name; - } else { - return ''; - } - }); +git.getCurrentBranch = async (repoPath) => { + const branches = await git(['branch'], repoPath).then(gitParser.parseGitBranches); + + let branch = branches.find((branch) => branch.current); + if (branch) { + return branch.name; + } else { + return ''; + } }; -git.discardAllChanges = (repoPath) => { - return git(['reset', '--hard', 'HEAD'], repoPath).then(() => { - return git(['clean', '-fd'], repoPath); - }); +git.discardAllChanges = async (repoPath) => { + await git(['reset', '--hard', 'HEAD'], repoPath); + return git(['clean', '-fd'], repoPath); }; -git.discardChangesInFile = (repoPath, filename) => { - return git.status(repoPath, filename).then((status) => { - if (Object.keys(status.files).length == 0) - throw new Error(`No files in status in discard, filename: ${filename}`); - const fileStatus = status.files[Object.keys(status.files)[0]]; - const fullPath = path.join(repoPath, filename); - - if (fileStatus.staged) { - // if staged, just remove from git - return git(['rm', '-f', filename], repoPath); - } else if (fileStatus.isNew) { - // new file, junst unlink - return fs.unlink(fullPath).catch((err) => { - throw { command: 'unlink', error: err }; - }); - } +git.discardChangesInFile = async (repoPath, filename) => { + const status = await git.status(repoPath, filename); + if (Object.keys(status.files).length == 0) + throw new Error(`No files in status in discard, filename: ${filename}`); + const fileStatus = status.files[Object.keys(status.files)[0]]; + const fullPath = path.join(repoPath, filename); + + if (fileStatus.staged) { + // if staged, just remove from git + return git(['rm', '-f', filename], repoPath); + } else if (fileStatus.isNew) { + // new file, junst unlink + return fs.unlink(fullPath).catch((err) => { + throw { command: 'unlink', error: err }; + }); + } - return fs - .stat(fullPath) - .then((stats) => stats.isDirectory()) - .catch(() => false) - .then((isSubrepoChange) => { - if (isSubrepoChange) { - return git(['submodule', 'sync'], repoPath).then(() => - git(['submodule', 'update', '--init', '-f', '--recursive', filename], repoPath) - ); - } else { - return git(['checkout', 'HEAD', '--', filename], repoPath); - } - }); - }); + const isSubrepoChange = await fs + .stat(fullPath) + .then((stats) => stats.isDirectory()) + .catch(() => false); + + if (isSubrepoChange) { + return git(['submodule', 'sync'], repoPath).then(() => + git(['submodule', 'update', '--init', '-f', '--recursive', filename], repoPath) + ); + } else { + return git(['checkout', 'HEAD', '--', filename], repoPath); + } }; git.applyPatchedDiff = (repoPath, patchedDiff) => { @@ -482,112 +467,116 @@ git.applyPatchedDiff = (repoPath, patchedDiff) => { } }; -git.commit = (repoPath, amend, emptyCommit, message, files) => { - return new Promise((resolve, reject) => { - if (message == undefined) { - reject({ error: 'Must specify commit message' }); - } - if ((!Array.isArray(files) || files.length == 0) && !amend && !emptyCommit) { - reject({ error: 'Must specify files or amend to commit' }); - } - resolve(); - }) - .then(() => { - return git.status(repoPath); +git.commit = async (repoPath, amend, emptyCommit, message, files) => { + try { + await new Promise((resolve, reject) => { + if (message == undefined) { + reject({ error: 'Must specify commit message' }); + } + if ((!Array.isArray(files) || files.length == 0) && !amend && !emptyCommit) { + reject({ error: 'Must specify files or amend to commit' }); + } + resolve(); }) - .then((status) => { - const toAdd = []; - const toRemove = []; - const promises = []; // promises that patches each files individually - - for (let v in files) { - let file = files[v]; - let fileStatus = - status.files[file.name] || status.files[path.relative(repoPath, file.name)]; - if (!fileStatus) { - throw { error: `No such file in staging: ${file.name}` }; - } + .then(() => { + return git.status(repoPath); + }) + .then((status) => { + const toAdd = []; + const toRemove = []; + const promises = []; // promises that patches each files individually + + for (let v in files) { + let file = files[v]; + let fileStatus = + status.files[file.name] || status.files[path.relative(repoPath, file.name)]; + if (!fileStatus) { + throw { error: `No such file in staging: ${file.name}` }; + } - if (fileStatus.removed) { - toRemove.push(file.name.trim()); - } else if (files[v].patchLineList) { - promises.push( - git(['diff', '--', file.name.trim()], repoPath) - .then(gitParser.parsePatchDiffResult.bind(null, file.patchLineList)) - .then(git.applyPatchedDiff.bind(null, repoPath)) - ); - } else { - toAdd.push(file.name.trim()); + if (fileStatus.removed) { + toRemove.push(file.name.trim()); + } else if (files[v].patchLineList) { + promises.push( + git(['diff', '--', file.name.trim()], repoPath) + .then(gitParser.parsePatchDiffResult.bind(null, file.patchLineList)) + .then(git.applyPatchedDiff.bind(null, repoPath)) + ); + } else { + toAdd.push(file.name.trim()); + } } - } - promises.push( - Promise.resolve() - .then(() => { - if (toRemove.length > 0) - return git( - ['update-index', '--remove', '--stdin'], - repoPath, - null, - null, - toRemove.join('\n') - ); - }) - .then(() => { - if (toAdd.length > 0) - return git( - ['update-index', '--add', '--stdin'], - repoPath, - null, - null, - toAdd.join('\n') - ); - }) - ); + promises.push( + Promise.resolve() + .then(() => { + if (toRemove.length > 0) + return git( + ['update-index', '--remove', '--stdin'], + repoPath, + null, + null, + toRemove.join('\n') + ); + }) + .then(() => { + if (toAdd.length > 0) + return git( + ['update-index', '--add', '--stdin'], + repoPath, + null, + null, + toAdd.join('\n') + ); + }) + ); - return Promise.all(promises); - }) - .then(() => { - const ammendFlag = amend ? '--amend' : ''; - const allowedEmptyFlag = emptyCommit || amend ? '--allow-empty' : ''; - const isGPGSign = config.isForceGPGSign ? '-S' : ''; - return git( - ['commit', ammendFlag, allowedEmptyFlag, isGPGSign, '--file=-'], - repoPath, - null, - null, - message - ); - }) - .catch((err) => { - // ignore the case where nothing were added to be committed - if (!err.stdout || err.stdout.indexOf('Changes not staged for commit') === -1) { - throw err; - } - }); + return Promise.all(promises); + }); + + const ammendFlag = amend ? '--amend' : ''; + const allowedEmptyFlag = emptyCommit || amend ? '--allow-empty' : ''; + const isGPGSign = config.isForceGPGSign ? '-S' : ''; + return git( + ['commit', ammendFlag, allowedEmptyFlag, isGPGSign, '--file=-'], + repoPath, + null, + null, + message + ); + } catch (err) { + // ignore the case where nothing were added to be committed + if (!err.stdout || err.stdout.indexOf('Changes not staged for commit') === -1) { + throw err; + } + } }; -git.revParse = (repoPath) => { - return git(['rev-parse', '--is-inside-work-tree', '--is-bare-repository'], repoPath) - .then((result) => { - const resultLines = result.split('\n'); - if (resultLines[1].indexOf('true') > -1) { - // bare repositories don't support `--show-toplevel` since git 2.25 - return { type: 'bare', gitRootPath: repoPath }; +git.revParse = async (repoPath) => { + try { + const result = await git( + ['rev-parse', '--is-inside-work-tree', '--is-bare-repository'], + repoPath + ); + const resultLines = result.split('\n'); + if (resultLines[1].indexOf('true') > -1) { + // bare repositories don't support `--show-toplevel` since git 2.25 + return { type: 'bare', gitRootPath: repoPath }; + } + return git(['rev-parse', '--show-toplevel'], repoPath).then((topLevel) => { + const rootPath = path.normalize(topLevel.trim() ? topLevel.trim() : repoPath); + if (resultLines[0].indexOf('true') > -1) { + return { type: 'inited', gitRootPath: rootPath }; } - return git(['rev-parse', '--show-toplevel'], repoPath).then((topLevel) => { - const rootPath = path.normalize(topLevel.trim() ? topLevel.trim() : repoPath); - if (resultLines[0].indexOf('true') > -1) { - return { type: 'inited', gitRootPath: rootPath }; - } - return { type: 'uninited', gitRootPath: rootPath }; - }); - }) - .catch((err) => ({ type: 'uninited', gitRootPath: path.normalize(repoPath) })); + return { type: 'uninited', gitRootPath: rootPath }; + }); + } catch (err) { + return { type: 'uninited', gitRootPath: path.normalize(repoPath) }; + } }; -git.log = (path, limit, skip, maxActiveBranchSearchIteration) => { - return git( +git.log = async (path, limit, skip, maxActiveBranchSearchIteration) => { + let log = await git( [ 'log', '--cc', @@ -607,30 +596,28 @@ git.log = (path, limit, skip, maxActiveBranchSearchIteration) => { `--skip=${skip}`, ], path - ) - .then(gitParser.parseGitLog) - .then((log) => { - log = log ? log : []; - if (maxActiveBranchSearchIteration > 0 && !log.isHeadExist && log.length > 0) { - return git - .log( - path, - config.numberOfNodesPerLoad + limit, - config.numberOfNodesPerLoad + skip, - maxActiveBranchSearchIteration - 1 - ) - .then((innerLog) => { - return { - limit: limit + (innerLog.isHeadExist ? 0 : config.numberOfNodesPerLoad), - skip: skip + (innerLog.isHeadExist ? 0 : config.numberOfNodesPerLoad), - nodes: log.concat(innerLog.nodes), - isHeadExist: innerLog.isHeadExist, - }; - }); - } else { - return { limit: limit, skip: skip, nodes: log, isHeadExist: log.isHeadExist }; - } - }); + ).then(gitParser.parseGitLog); + + log = log ? log : []; + if (maxActiveBranchSearchIteration > 0 && !log.isHeadExist && log.length > 0) { + return git + .log( + path, + config.numberOfNodesPerLoad + limit, + config.numberOfNodesPerLoad + skip, + maxActiveBranchSearchIteration - 1 + ) + .then((innerLog) => { + return { + limit: limit + (innerLog.isHeadExist ? 0 : config.numberOfNodesPerLoad), + skip: skip + (innerLog.isHeadExist ? 0 : config.numberOfNodesPerLoad), + nodes: log.concat(innerLog.nodes), + isHeadExist: innerLog.isHeadExist, + }; + }); + } else { + return { limit: limit, skip: skip, nodes: log, isHeadExist: log.isHeadExist }; + } }; module.exports = git; diff --git a/source/server.js b/source/server.js index a77820978..8b2626ffe 100644 --- a/source/server.js +++ b/source/server.js @@ -199,21 +199,20 @@ if (config.authentication) { }; } -const indexHtmlCacheKey = cache.registerFunc(() => { - return cache.resolveFunc(pluginsCacheKey).then((plugins) => { - return fs.readFile(__dirname + '/../public/index.html').then((data) => { - return Promise.all( - Object.values(plugins).map((plugin) => { - return plugin.compile(); - }) - ).then((results) => { - data = data.toString().replace('', results.join('\n\n')); - data = data.replace(/__ROOT_PATH__/g, config.rootPath); - - return data; - }); - }); - }); +const indexHtmlCacheKey = cache.registerFunc(async () => { + const plugins = await cache.resolveFunc(pluginsCacheKey); + let data = await fs.readFile(__dirname + '/../public/index.html'); + + const results = await Promise.all( + Object.values(plugins).map((plugin) => { + return plugin.compile(); + }) + ); + + data = data.toString().replace('', results.join('\n\n')); + data = data.replace(/__ROOT_PATH__/g, config.rootPath); + + return data; }); app.get('/', (req, res) => { @@ -262,51 +261,48 @@ const apiEnvironment = { gitApi.registerApi(apiEnvironment); // Init plugins -const loadPlugins = (plugins, pluginBasePath) => { - return fs.readdir(pluginBasePath, { withFileTypes: true }).then((files) => { - return Promise.all( - files.map((pluginDir) => { - // if not a directory or doesn't contain an ungit-plugin.json, just skip it. - if (!pluginDir.isDirectory()) { +const loadPlugins = async (plugins, pluginBasePath) => { + const files = await fs.readdir(pluginBasePath, { withFileTypes: true }); + return Promise.all( + files.map(async (pluginDir) => { + // if not a directory or doesn't contain an ungit-plugin.json, just skip it. + if (!pluginDir.isDirectory()) { + return; + } + const pluginPath = path.join(pluginBasePath, pluginDir.name); + + try { + await fs.access(path.join(pluginPath, 'ungit-plugin.json')); + + winston.info('Loading plugin: ' + pluginPath); + const plugin = new UngitPlugin({ + dir: pluginDir.name, + httpBasePath: 'plugins/' + pluginDir.name, + path: pluginPath, + }); + if (plugin.manifest.disabled || plugin.config.disabled) { + winston.info('Plugin disabled: ' + pluginDir.name); return; } - const pluginPath = path.join(pluginBasePath, pluginDir.name); - return fs - .access(path.join(pluginPath, 'ungit-plugin.json')) - .then(() => { - winston.info('Loading plugin: ' + pluginPath); - const plugin = new UngitPlugin({ - dir: pluginDir.name, - httpBasePath: 'plugins/' + pluginDir.name, - path: pluginPath, - }); - if (plugin.manifest.disabled || plugin.config.disabled) { - winston.info('Plugin disabled: ' + pluginDir.name); - return; - } - plugin.init(apiEnvironment); - plugins.push(plugin); - winston.info('Plugin loaded: ' + pluginDir.name); - }) - .catch(() => { - /* ignore */ - }); - }) - ); - }); + plugin.init(apiEnvironment); + plugins.push(plugin); + winston.info('Plugin loaded: ' + pluginDir.name); + } catch (error) {} + }) + ); }; -const pluginsCacheKey = cache.registerFunc(() => { +const pluginsCacheKey = cache.registerFunc(async () => { const plugins = []; - return loadPlugins(plugins, path.join(__dirname, '..', 'components')) - .then(() => { - return fs - .access(config.pluginDirectory) - .then(() => loadPlugins(plugins, config.pluginDirectory)) - .catch(() => { - /* ignore */ - }); - }) - .then(() => plugins); + + await loadPlugins(plugins, path.join(__dirname, '..', 'components')).then(async () => { + try { + await fs.access(config.pluginDirectory); + + return loadPlugins(plugins, config.pluginDirectory); + } catch (error) {} + }); + + return plugins; }); app.get('/serverdata.js', (req, res) => { @@ -359,23 +355,22 @@ app.get('/api/gitversion', (req, res) => { }); const userConfigPath = path.join(config.homedir, '.ungitrc'); -const readUserConfig = () => { - return fs - .access(userConfigPath) - .then(() => { - return fs - .readFile(userConfigPath, { encoding: 'utf8' }) - .then((content) => { - return JSON.parse(content.toString()); - }) - .catch((err) => { - winston.error(`Stop at reading ~/.ungitrc because ${err}`); - process.exit(0); - }); - }) - .catch(() => { - return {}; - }); +const readUserConfig = async () => { + try { + await fs.access(userConfigPath); + + return fs + .readFile(userConfigPath, { encoding: 'utf8' }) + .then((content) => { + return JSON.parse(content.toString()); + }) + .catch((err) => { + winston.error(`Stop at reading ~/.ungitrc because ${err}`); + process.exit(0); + }); + } catch (error) { + return {}; + } }; const writeUserConfig = (configContent) => { return fs.writeFile(userConfigPath, JSON.stringify(configContent, undefined, 2)); diff --git a/source/ungit-plugin.js b/source/ungit-plugin.js index c6481e37d..234665155 100644 --- a/source/ungit-plugin.js +++ b/source/ungit-plugin.js @@ -39,18 +39,17 @@ class UngitPlugin { env.app.use(`/plugins/${this.name}`, express.static(this.path)); } - compile() { + async compile() { winston.info(`Compiling plugin ${this.path}`); const exports = this.manifest.exports || {}; - return Promise.resolve() + const result = await Promise.resolve() .then(() => { if (exports.raw) { return Promise.all( - assureArray(exports.raw).map((rawSource) => { - return fs.readFile(path.join(this.path, rawSource)).then((text) => { - return text + '\n'; - }); + assureArray(exports.raw).map(async (rawSource) => { + const text = await fs.readFile(path.join(this.path, rawSource)); + return text + '\n'; }) ).then((result) => { return result.join('\n'); @@ -76,12 +75,12 @@ class UngitPlugin { .then((result) => { if (exports.knockoutTemplates) { return Promise.all( - Object.keys(exports.knockoutTemplates).map((templateName) => { - return fs - .readFile(path.join(this.path, exports.knockoutTemplates[templateName])) - .then((text) => { - return ``; - }); + Object.keys(exports.knockoutTemplates).map(async (templateName) => { + const text = await fs.readFile( + path.join(this.path, exports.knockoutTemplates[templateName]) + ); + + return ``; }) ).then((templates) => { return result + templates.join('\n'); @@ -103,10 +102,9 @@ class UngitPlugin { } else { return result; } - }) - .then((result) => { - return `\n${result}`; }); + + return `\n${result}`; } } module.exports = UngitPlugin; diff --git a/source/utils/cache.js b/source/utils/cache.js index 6e67fd324..8bdf3afb6 100644 --- a/source/utils/cache.js +++ b/source/utils/cache.js @@ -9,7 +9,7 @@ const funcMap = {}; // Will there ever be a use case where this is a cache with * @param {string} [key] - A key associated with a function to be executed. * @return {Promise} - Promise either resolved with cached result of the function or rejected with function not found. */ -cache.resolveFunc = (key) => { +cache.resolveFunc = async (key) => { let result = cache.get(key); if (result !== undefined) { return Promise.resolve(result); @@ -23,11 +23,12 @@ cache.resolveFunc = (key) => { } catch (err) { return Promise.reject(err); } - return Promise.resolve(result) // func is found, resolve, set with TTL and return result - .then((r) => { - cache.set(key, r, funcMap[key].ttl); - return r; - }); + + const r = await // func is found, resolve, set with TTL and return result + Promise.resolve(result); + + cache.set(key, r, funcMap[key].ttl); + return r; }; /** diff --git a/test/common-es6.js b/test/common-es6.js index 949329712..a6f1927ae 100644 --- a/test/common-es6.js +++ b/test/common-es6.js @@ -49,23 +49,23 @@ exports.post = this.makeRequest.bind(this, 'POST'); exports.delete = this.makeRequest.bind(this, 'DELETE'); exports.put = this.makeRequest.bind(this, 'PUT'); -exports.initRepo = (req, config) => { +exports.initRepo = async (req, config) => { config = config || {}; - return this.post(req, '/testing/createtempdir', config.path).then((res) => { - expect(res.path).to.be.ok(); - return this.post(req, '/init', { path: res.path, bare: !!config.bare }).then(() => res.path); - }); + const res = await this.post(req, '/testing/createtempdir', config.path); + expect(res.path).to.be.ok(); + await this.post(req, '/init', { path: res.path, bare: !!config.bare }); + return res.path; }; -exports.createSmallRepo = (req) => { - return this.initRepo(req).then((dir) => { - const testFile = 'smalltestfile.txt'; - return this.post(req, '/testing/createfile', { file: path.join(dir, testFile) }) - .then(() => - this.post(req, '/commit', { path: dir, message: 'Init', files: [{ name: testFile }] }) - ) - .then(() => dir); - }); +exports.createSmallRepo = async (req) => { + const dir = await this.initRepo(req); + const testFile = 'smalltestfile.txt'; + + await this.post(req, '/testing/createfile', { file: path.join(dir, testFile) }).then(() => + this.post(req, '/commit', { path: dir, message: 'Init', files: [{ name: testFile }] }) + ); + + return dir; }; // Used by ko tests, which doesn't really require dom manipulation, but does require these things to be defined. diff --git a/test/spec.cache.js b/test/spec.cache.js index 2b5a29226..568749ca0 100644 --- a/test/spec.cache.js +++ b/test/spec.cache.js @@ -2,54 +2,53 @@ const expect = require('expect.js'); const cache = require('../source/utils/cache'); describe('cache', () => { - it('should be invokable several times', () => { + it('should be invokable several times', async () => { let i = 0; const key = cache.registerFunc(() => i++); - return cache + const val = await cache .resolveFunc(key) .then((val) => { expect(val).to.be(0); }) - .then(() => cache.resolveFunc(key)) - .then((val) => expect(val).to.be(0)); + .then(() => cache.resolveFunc(key)); + + return expect(val).to.be(0); }); - it('should work when failing sync', () => { + it('should work when failing sync', async () => { const errorMsg = 'A nasty error...'; const key = cache.registerFunc(() => { throw new Error(errorMsg); }); - return cache - .resolveFunc(key) - .then(() => { - throw new Error('should have thrown exception!'); - }) - .catch((e) => { - if (e.message !== errorMsg) throw new Error('error message does not match!'); - }); + try { + await cache.resolveFunc(key); + + throw new Error('should have thrown exception!'); + } catch (e) { + if (e.message !== errorMsg) throw new Error('error message does not match!'); + } }); - it('should work when failing async', () => { + it('should work when failing async', async () => { const errorMsg = 'A nasty error...'; const key = cache.registerFunc(() => Promise.reject(new Error(errorMsg))); - return cache - .resolveFunc(key) - .then(() => { - throw new Error('should have thrown exception!'); - }) - .catch((e) => { - if (e.message !== errorMsg) throw new Error('error message does not match!'); - }); + try { + await cache.resolveFunc(key); + + throw new Error('should have thrown exception!'); + } catch (e) { + if (e.message !== errorMsg) throw new Error('error message does not match!'); + } }); - it('should be possible to invalidate cache', () => { + it('should be possible to invalidate cache', async () => { let i = 0; const key = cache.registerFunc(() => i++); - return cache + const val = await cache .resolveFunc(key) .then((val) => { expect(val).to.be(0); @@ -57,13 +56,12 @@ describe('cache', () => { .then(() => { cache.invalidateFunc(key); return cache.resolveFunc(key); - }) - .then((val) => { - expect(val).to.be(1); }); + + expect(val).to.be(1); }); - it('creating a same function with different keys', () => { + it('creating a same function with different keys', async () => { let i = 0; const key1 = 'func1'; const key2 = 'func2'; @@ -71,7 +69,7 @@ describe('cache', () => { cache.registerFunc(key1, func); cache.registerFunc(key2, func); - return cache + const val = await cache .resolveFunc(key1) .then((val) => { expect(val).to.be(0); @@ -91,19 +89,18 @@ describe('cache', () => { .then((val) => { expect(val).to.be(2); }) - .then(() => cache.resolveFunc(key2)) - .then((val) => { - expect(val).to.be(1); - }); + .then(() => cache.resolveFunc(key2)); + + expect(val).to.be(1); }); - it('Testing ttl', function () { + it('Testing ttl', async function () { let i = 0; const func = () => i++; const key = cache.registerFunc(1, null, func); this.timeout(3000); - return cache + const val = await cache .resolveFunc(key) .then((val) => { expect(val).to.be(0); @@ -123,9 +120,8 @@ describe('cache', () => { expect(val).to.be(1); }) .then(() => new Promise((resolve) => setTimeout(resolve, 500))) - .then(() => cache.resolveFunc(key)) - .then((val) => { - expect(val).to.be(1); - }); + .then(() => cache.resolveFunc(key)); + + expect(val).to.be(1); }); }); diff --git a/test/spec.git-api.branching.js b/test/spec.git-api.branching.js index 2ae71fb1e..38997bdc1 100644 --- a/test/spec.git-api.branching.js +++ b/test/spec.git-api.branching.js @@ -18,132 +18,123 @@ const req = request(app); describe('git-api branching', function () { this.timeout(8000); - before(() => { - return common + before(async () => { + const res = await common .initRepo(req) .then((res) => { testDir = res; }) - .then(() => common.get(req, '/gitconfig', { path: testDir })) - .then((res) => { - gitConfig = res; - }); + .then(() => common.get(req, '/gitconfig', { path: testDir })); + + gitConfig = res; }); after(() => common.post(req, '/testing/cleanup')); const commitMessage = 'Commit 1'; const testFile1 = 'testfile1.txt'; - it('should be possible to commit to master', () => { - return common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ); - }); - - it('listing branches should work', () => { - return common.get(req, '/branches', { path: testDir }).then((res) => { - expect(res.length).to.be(1); - expect(res[0].name).to.be('master'); - expect(res[0].current).to.be(true); + it('should be possible to commit to master', async () => { + await common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }); + + return common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], }); }); + it('listing branches should work', async () => { + const res = await common.get(req, '/branches', { path: testDir }); + expect(res.length).to.be(1); + expect(res[0].name).to.be('master'); + expect(res[0].current).to.be(true); + }); + const testBranch = 'testBranch'; it('creating a branch should work', () => { return common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }); }); - it('listing branches should show the new branch', () => { - return common.get(req, '/branches', { path: testDir }).then((res) => { - expect(res.length).to.be(2); - expect(res[0].name).to.be('master'); - expect(res[0].current).to.be(true); - expect(res[1].name).to.be(testBranch); - expect(res[1].current).to.be(undefined); - }); + it('listing branches should show the new branch', async () => { + const res = await common.get(req, '/branches', { path: testDir }); + expect(res.length).to.be(2); + expect(res[0].name).to.be('master'); + expect(res[0].current).to.be(true); + expect(res[1].name).to.be(testBranch); + expect(res[1].current).to.be(undefined); }); it('should be possible to switch to a branch', () => { return common.post(req, '/checkout', { path: testDir, name: testBranch }); }); - it('listing branches should show the new branch as current', () => { - return common.get(req, '/branches', { path: testDir }).then((res) => { - expect(res.length).to.be(2); - expect(res[0].name).to.be('master'); - expect(res[0].current).to.be(undefined); - expect(res[1].name).to.be(testBranch); - expect(res[1].current).to.be(true); - }); + it('listing branches should show the new branch as current', async () => { + const res = await common.get(req, '/branches', { path: testDir }); + expect(res.length).to.be(2); + expect(res[0].name).to.be('master'); + expect(res[0].current).to.be(undefined); + expect(res[1].name).to.be(testBranch); + expect(res[1].current).to.be(true); }); - it('get branch should show the new branch as current', () => { - return common - .get(req, '/checkout', { path: testDir }) - .then((res) => expect(res).to.be(testBranch)); + it('get branch should show the new branch as current', async () => { + const res = await common.get(req, '/checkout', { path: testDir }); + + return expect(res).to.be(testBranch); }); const commitMessage3 = 'Commit 3'; const testFile2 = 'testfile2.txt'; - it('should be possible to commit to the branch', () => { - return common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile2) }) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage3, - files: [{ name: testFile2 }], - }) - ); - }); - - it('log should show both branches and all commits', () => { - return common.get(req, '/gitlog', { path: testDir }).then((res) => { - expect(res.skip).to.be(0); - expect(res.limit).to.be(25); - - const nodes = res.nodes; - expect(nodes).to.be.a('array'); - expect(nodes.length).to.be(2); - const objs = {}; - nodes.forEach((obj) => { - obj.refs.sort(); - objs[obj.refs[0]] = obj; - }); - const master = objs['refs/heads/master']; - const HEAD = objs['HEAD']; - expect(master.message.indexOf(commitMessage)).to.be(0); - expect(master.authorDate).to.be.a('string'); - expect(master.authorName).to.be(gitConfig['user.name']); - expect(master.authorEmail).to.be(gitConfig['user.email']); - expect(master.commitDate).to.be.a('string'); - expect(master.committerName).to.be(gitConfig['user.name']); - expect(master.committerEmail).to.be(gitConfig['user.email']); - expect(master.refs).to.eql(['refs/heads/master']); - expect(master.parents).to.eql([]); - expect(master.sha1).to.be.ok(); - - expect(HEAD.message.indexOf(commitMessage3)).to.be(0); - expect(HEAD.authorDate).to.be.a('string'); - expect(HEAD.authorName).to.be(gitConfig['user.name']); - expect(HEAD.authorEmail).to.be(gitConfig['user.email']); - expect(HEAD.commitDate).to.be.a('string'); - expect(HEAD.committerName).to.be(gitConfig['user.name']); - expect(HEAD.committerEmail).to.be(gitConfig['user.email']); - expect(HEAD.refs).to.eql(['HEAD', `refs/heads/${testBranch}`]); - expect(HEAD.parents).to.eql([master.sha1]); - expect(HEAD.sha1).to.be.ok(); + it('should be possible to commit to the branch', async () => { + await common.post(req, '/testing/createfile', { file: path.join(testDir, testFile2) }); + + return common.post(req, '/commit', { + path: testDir, + message: commitMessage3, + files: [{ name: testFile2 }], }); }); + it('log should show both branches and all commits', async () => { + const res = await common.get(req, '/gitlog', { path: testDir }); + expect(res.skip).to.be(0); + expect(res.limit).to.be(25); + + const nodes = res.nodes; + expect(nodes).to.be.a('array'); + expect(nodes.length).to.be(2); + const objs = {}; + nodes.forEach((obj) => { + obj.refs.sort(); + objs[obj.refs[0]] = obj; + }); + const master = objs['refs/heads/master']; + const HEAD = objs['HEAD']; + expect(master.message.indexOf(commitMessage)).to.be(0); + expect(master.authorDate).to.be.a('string'); + expect(master.authorName).to.be(gitConfig['user.name']); + expect(master.authorEmail).to.be(gitConfig['user.email']); + expect(master.commitDate).to.be.a('string'); + expect(master.committerName).to.be(gitConfig['user.name']); + expect(master.committerEmail).to.be(gitConfig['user.email']); + expect(master.refs).to.eql(['refs/heads/master']); + expect(master.parents).to.eql([]); + expect(master.sha1).to.be.ok(); + + expect(HEAD.message.indexOf(commitMessage3)).to.be(0); + expect(HEAD.authorDate).to.be.a('string'); + expect(HEAD.authorName).to.be(gitConfig['user.name']); + expect(HEAD.authorEmail).to.be(gitConfig['user.email']); + expect(HEAD.commitDate).to.be.a('string'); + expect(HEAD.committerName).to.be(gitConfig['user.name']); + expect(HEAD.committerEmail).to.be(gitConfig['user.email']); + expect(HEAD.refs).to.eql(['HEAD', `refs/heads/${testBranch}`]); + expect(HEAD.parents).to.eql([master.sha1]); + expect(HEAD.sha1).to.be.ok(); + }); + it('should be possible to modify some local file', () => { return common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }); }); @@ -152,22 +143,21 @@ describe('git-api branching', function () { return common.post(req, '/checkout', { path: testDir, name: 'master' }); }); - it('status should list the changed file', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile1]).to.eql({ - displayName: testFile1, - fileName: testFile1, - oldFileName: testFile1, - isNew: false, - staged: false, - removed: false, - conflict: false, - renamed: false, - type: 'text', - additions: '1', - deletions: '1', - }); + it('status should list the changed file', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile1]).to.eql({ + displayName: testFile1, + fileName: testFile1, + oldFileName: testFile1, + isNew: false, + staged: false, + removed: false, + conflict: false, + renamed: false, + type: 'text', + additions: '1', + deletions: '1', }); }); @@ -175,25 +165,27 @@ describe('git-api branching', function () { return common.post(req, '/tags', { path: testDir, name: 'v1.0' }); }); - it('should be possible to list tag', () => { - return common.get(req, '/tags', { path: testDir }).then((res) => expect(res.length).to.be(1)); + it('should be possible to list tag', async () => { + const res = await common.get(req, '/tags', { path: testDir }); + return expect(res.length).to.be(1); }); it('should be possible to delete a tag', () => { return common.delete(req, '/tags', { path: testDir, name: 'v1.0' }); }); - it('tag should be removed', () => { - return common.get(req, '/tags', { path: testDir }).then((res) => expect(res.length).to.be(0)); + it('tag should be removed', async () => { + const res = await common.get(req, '/tags', { path: testDir }); + return expect(res.length).to.be(0); }); it('should be possible to delete a branch', () => { return common.delete(req, '/branches', { path: testDir, name: testBranch }); }); - it('branch should be removed', () => { - return common - .get(req, '/branches', { path: testDir }) - .then((res) => expect(res.length).to.be(1)); + it('branch should be removed', async () => { + const res = await common.get(req, '/branches', { path: testDir }); + + return expect(res.length).to.be(1); }); }); diff --git a/test/spec.git-api.conflict-no-auto-stash.js b/test/spec.git-api.conflict-no-auto-stash.js index 5039aaf27..f78e86f9b 100644 --- a/test/spec.git-api.conflict-no-auto-stash.js +++ b/test/spec.git-api.conflict-no-auto-stash.js @@ -18,23 +18,24 @@ describe('git-api conflict checkout no auto stash', function () { const testBranch = 'testBranch'; const testFile1 = 'testfile1.txt'; - before(() => { - return common.initRepo(req).then((dir) => { - testDir = dir; - return common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'a', files: [{ name: testFile1 }] }) - ) - .then(() => - common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) - ) - .then(() => - common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }) - ) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'b', files: [{ name: testFile1 }] }) - ); + before(async () => { + const dir = await common.initRepo(req); + testDir = dir; + + await common + .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) + .then(() => + common.post(req, '/commit', { path: testDir, message: 'a', files: [{ name: testFile1 }] }) + ) + .then(() => + common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) + ) + .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })); + + return common.post(req, '/commit', { + path: testDir, + message: 'b', + files: [{ name: testFile1 }], }); }); after(() => { @@ -45,15 +46,18 @@ describe('git-api conflict checkout no auto stash', function () { return common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }); }); - it('should not be possible to checkout with local files that will conflict', () => { - return common - .post(req, `${restGit.pathPrefix}/checkout`, { path: testDir, name: testBranch }) - .then((gitErr) => expect(gitErr.errorCode).to.be('local-changes-would-be-overwritten')); + it('should not be possible to checkout with local files that will conflict', async () => { + const gitErr = await common.post(req, `${restGit.pathPrefix}/checkout`, { + path: testDir, + name: testBranch, + }); + + return expect(gitErr.errorCode).to.be('local-changes-would-be-overwritten'); }); - it('checkout should say we are still on master', () => { - return common - .get(req, '/checkout', { path: testDir }) - .then((res) => expect(res).to.be('master')); + it('checkout should say we are still on master', async () => { + const res = await common.get(req, '/checkout', { path: testDir }); + + return expect(res).to.be('master'); }); }); diff --git a/test/spec.git-api.conflict.js b/test/spec.git-api.conflict.js index 5ee386d8c..57eda0c10 100644 --- a/test/spec.git-api.conflict.js +++ b/test/spec.git-api.conflict.js @@ -21,43 +21,37 @@ describe('git-api conflict rebase', function () { const testFile1 = 'testfile1.txt'; const testBranch = 'testBranch'; - before(() => { - return common.initRepo(req).then((dir) => { - testDir = dir; - - return common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ) - .then(() => - common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) - ) - .then(() => - common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }) - ) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ) - .then(() => common.post(req, '/checkout', { path: testDir, name: testBranch })) - .then(() => - common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }) - ) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ); + before(async () => { + const dir = await common.initRepo(req); + testDir = dir; + + await common + .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) + .then(() => + common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], + }) + ) + .then(() => + common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) + ) + .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })) + .then(() => + common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], + }) + ) + .then(() => common.post(req, '/checkout', { path: testDir, name: testBranch })) + .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })); + + return common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], }); }); @@ -74,23 +68,22 @@ describe('git-api conflict rebase', function () { }); }); - it('status should list files in conflict', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(res.inRebase).to.be(true); - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile1]).to.eql({ - displayName: testFile1, - fileName: testFile1, - oldFileName: testFile1, - isNew: false, - staged: false, - removed: false, - conflict: true, - renamed: false, - type: 'text', - additions: '4', - deletions: '0', - }); + it('status should list files in conflict', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(res.inRebase).to.be(true); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile1]).to.eql({ + displayName: testFile1, + fileName: testFile1, + oldFileName: testFile1, + isNew: false, + staged: false, + removed: false, + conflict: true, + renamed: false, + type: 'text', + additions: '4', + deletions: '0', }); }); @@ -113,23 +106,24 @@ describe('git-api conflict checkout', function () { const testBranch = 'testBranch'; const testFile1 = 'testfile1.txt'; - before(() => { - return common.initRepo(req).then((dir) => { - testDir = dir; - return common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'a', files: [{ name: testFile1 }] }) - ) - .then(() => - common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) - ) - .then(() => - common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }) - ) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'b', files: [{ name: testFile1 }] }) - ); + before(async () => { + const dir = await common.initRepo(req); + testDir = dir; + + await common + .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) + .then(() => + common.post(req, '/commit', { path: testDir, message: 'a', files: [{ name: testFile1 }] }) + ) + .then(() => + common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) + ) + .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })); + + return common.post(req, '/commit', { + path: testDir, + message: 'b', + files: [{ name: testFile1 }], }); }); @@ -150,23 +144,22 @@ describe('git-api conflict checkout', function () { }); }); - it('status should list files in conflict', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(res.inRebase).to.be(false); - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile1]).to.eql({ - displayName: testFile1, - fileName: testFile1, - oldFileName: testFile1, - isNew: false, - staged: false, - removed: false, - conflict: true, - renamed: false, - type: 'text', - additions: '4', - deletions: '0', - }); + it('status should list files in conflict', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(res.inRebase).to.be(false); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile1]).to.eql({ + displayName: testFile1, + fileName: testFile1, + oldFileName: testFile1, + isNew: false, + staged: false, + removed: false, + conflict: true, + renamed: false, + type: 'text', + additions: '4', + deletions: '0', }); }); }); @@ -177,30 +170,29 @@ describe('git-api conflict merge', function () { const testBranch = 'testBranch1'; const testFile1 = 'testfile1.txt'; - before(() => { - return common.initRepo(req).then((dir) => { - testDir = dir; - return common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'a', files: [{ name: testFile1 }] }) - ) - .then(() => - common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) - ) - .then(() => - common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }) - ) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'b', files: [{ name: testFile1 }] }) - ) - .then(() => common.post(req, '/checkout', { path: testDir, name: testBranch })) - .then(() => - common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }) - ) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'c', files: [{ name: testFile1 }] }) - ); + before(async () => { + const dir = await common.initRepo(req); + testDir = dir; + + await common + .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) + .then(() => + common.post(req, '/commit', { path: testDir, message: 'a', files: [{ name: testFile1 }] }) + ) + .then(() => + common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) + ) + .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })) + .then(() => + common.post(req, '/commit', { path: testDir, message: 'b', files: [{ name: testFile1 }] }) + ) + .then(() => common.post(req, '/checkout', { path: testDir, name: testBranch })) + .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })); + + return common.post(req, '/commit', { + path: testDir, + message: 'c', + files: [{ name: testFile1 }], }); }); @@ -217,24 +209,23 @@ describe('git-api conflict merge', function () { }); }); - it('status should list files in conflict', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(res.inMerge).to.be(true); - expect(res.commitMessage).to.be.ok(); - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile1]).to.eql({ - displayName: testFile1, - fileName: testFile1, - oldFileName: testFile1, - isNew: false, - staged: false, - removed: false, - conflict: true, - renamed: false, - type: 'text', - additions: '4', - deletions: '0', - }); + it('status should list files in conflict', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(res.inMerge).to.be(true); + expect(res.commitMessage).to.be.ok(); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile1]).to.eql({ + displayName: testFile1, + fileName: testFile1, + oldFileName: testFile1, + isNew: false, + staged: false, + removed: false, + conflict: true, + renamed: false, + type: 'text', + additions: '4', + deletions: '0', }); }); @@ -250,21 +241,20 @@ describe('git-api conflict merge', function () { return common.post(req, '/merge/continue', { path: testDir, message: 'something' }); }); - it('log should show changes on the merge commit', () => { - return common.get(req, '/gitlog', { path: testDir }).then((res) => { - expect(res.nodes).to.be.a('array'); - expect(res.nodes.length).to.be(4); - expect(res.nodes[0].additions).to.eql(1); - expect(res.nodes[0].deletions).to.eql(1); - expect(res.nodes[0].fileLineDiffs.length).to.be(1); - expect(res.nodes[0].fileLineDiffs[0]).to.eql({ - additions: 1, - deletions: 1, - fileName: testFile1, - oldFileName: testFile1, - displayName: testFile1, - type: 'text', - }); + it('log should show changes on the merge commit', async () => { + const res = await common.get(req, '/gitlog', { path: testDir }); + expect(res.nodes).to.be.a('array'); + expect(res.nodes.length).to.be(4); + expect(res.nodes[0].additions).to.eql(1); + expect(res.nodes[0].deletions).to.eql(1); + expect(res.nodes[0].fileLineDiffs.length).to.be(1); + expect(res.nodes[0].fileLineDiffs[0]).to.eql({ + additions: 1, + deletions: 1, + fileName: testFile1, + oldFileName: testFile1, + displayName: testFile1, + type: 'text', }); }); }); @@ -276,43 +266,37 @@ describe('git-api conflict solve by deleting', function () { const testFile1 = 'testfile1.txt'; const testBranch = 'testBranch'; - before(() => { - return common.initRepo(req).then((dir) => { - testDir = dir; - - return common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ) - .then(() => - common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) - ) - .then(() => - common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }) - ) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ) - .then(() => common.post(req, '/checkout', { path: testDir, name: testBranch })) - .then(() => - common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }) - ) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ); + before(async () => { + const dir = await common.initRepo(req); + testDir = dir; + + await common + .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) + .then(() => + common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], + }) + ) + .then(() => + common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) + ) + .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })) + .then(() => + common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], + }) + ) + .then(() => common.post(req, '/checkout', { path: testDir, name: testBranch })) + .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })); + + return common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], }); }); @@ -329,23 +313,22 @@ describe('git-api conflict solve by deleting', function () { }); }); - it('status should list files in conflict', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(res.inRebase).to.be(true); - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile1]).to.eql({ - displayName: testFile1, - fileName: testFile1, - oldFileName: testFile1, - isNew: false, - staged: false, - removed: false, - conflict: true, - renamed: false, - type: 'text', - additions: '4', - deletions: '0', - }); + it('status should list files in conflict', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(res.inRebase).to.be(true); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile1]).to.eql({ + displayName: testFile1, + fileName: testFile1, + oldFileName: testFile1, + isNew: false, + staged: false, + removed: false, + conflict: true, + renamed: false, + type: 'text', + additions: '4', + deletions: '0', }); }); diff --git a/test/spec.git-api.diff.js b/test/spec.git-api.diff.js index 47187d54f..8df5781d4 100644 --- a/test/spec.git-api.diff.js +++ b/test/spec.git-api.diff.js @@ -15,12 +15,13 @@ const req = request(app); describe('git-api diff', () => { let testDir, testBareDir; - before(() => { - return common + before(async () => { + const dir = await common .initRepo(req) .then((dir) => (testDir = dir)) - .then(() => common.initRepo(req, { bare: true })) - .then((dir) => (testBareDir = dir)); + .then(() => common.initRepo(req, { bare: true })); + + return (testBareDir = dir); }); after(() => common.post(req, '/testing/cleanup', undefined)); @@ -47,18 +48,21 @@ describe('git-api diff', () => { return common.post(req, '/testing/createimagefile', { file: path.join(testDir, testImage) }); }); - it('diff on created file should work', () => { - return common.get(req, '/diff', { path: testDir, file: testFile }).then((res) => { - for (let i = 0; i < content.length; i++) { - expect(res.indexOf(content[i])).to.be.above(-1); - } - }); + it('diff on created file should work', async () => { + const res = await common.get(req, '/diff', { path: testDir, file: testFile }); + for (let i = 0; i < content.length; i++) { + expect(res.indexOf(content[i])).to.be.above(-1); + } }); - it('diff on image file should work', () => { - return common - .getPng(req, '/diff/image', { path: testDir, filename: testImage, version: 'current' }) - .then((res) => expect(res.toString()).to.be('png')); + it('diff on image file should work', async () => { + const res = await common.getPng(req, '/diff/image', { + path: testDir, + filename: testImage, + version: 'current', + }); + + return expect(res.toString()).to.be('png'); }); it('should be possible to commit a file', () => { @@ -76,31 +80,31 @@ describe('git-api diff', () => { }); }); - it('diff on first commit should work', () => { - return common - .get(req, '/gitlog', { path: testDir }) - .then((res) => { - expect(res.nodes.length).to.be(2); - return common.get(req, '/diff', { path: testDir, file: testFile, sha1: res.nodes[1].sha1 }); - }) - .then((res) => { - for (let i = 0; i < content.length; i++) { - expect(res.indexOf(content[i])).to.be.above(-1); - } - }); + it('diff on first commit should work', async () => { + const res = await common.get(req, '/gitlog', { path: testDir }).then((res) => { + expect(res.nodes.length).to.be(2); + return common.get(req, '/diff', { path: testDir, file: testFile, sha1: res.nodes[1].sha1 }); + }); + + for (let i = 0; i < content.length; i++) { + expect(res.indexOf(content[i])).to.be.above(-1); + } }); - it('diff on commited file should work', () => { - return common.get(req, '/diff', { path: testDir, file: testFile }).then((res) => { - expect(res).to.be.an('array'); - expect(res.length).to.be(0); - }); + it('diff on commited file should work', async () => { + const res = await common.get(req, '/diff', { path: testDir, file: testFile }); + expect(res).to.be.an('array'); + expect(res.length).to.be(0); }); - it('diff on commited image file should work', () => { - return common - .getPng(req, '/diff/image', { path: testDir, filename: testImage, version: 'current' }) - .then((res) => expect(res.toString()).to.be('png')); + it('diff on commited image file should work', async () => { + const res = await common.getPng(req, '/diff/image', { + path: testDir, + filename: testImage, + version: 'current', + }); + + return expect(res.toString()).to.be('png'); }); it('should be possible to modify a file', () => { @@ -115,36 +119,40 @@ describe('git-api diff', () => { return common.post(req, '/testing/changeimagefile', { file: path.join(testDir, testImage) }); }); - it('diff on modified file should work', () => { - return common.get(req, '/diff', { path: testDir, file: testFile }).then((res) => { - expect(res.indexOf('diff --git a/afile.txt b/afile.txt')).to.be.above(-1); - expect(res.indexOf('+more')).to.be.above(-1); - }); + it('diff on modified file should work', async () => { + const res = await common.get(req, '/diff', { path: testDir, file: testFile }); + expect(res.indexOf('diff --git a/afile.txt b/afile.txt')).to.be.above(-1); + expect(res.indexOf('+more')).to.be.above(-1); }); - it('diff on file commit should work if file is changing', () => { - return common - .get(req, '/gitlog', { path: testDir }) - .then((res) => { - expect(res.nodes.length).to.be(2); - return common.get(req, '/diff', { path: testDir, file: testFile, sha1: res.nodes[1].sha1 }); - }) - .then((res) => { - expect(res.indexOf('diff --git a/afile.txt b/afile.txt')).to.be.above(-1); - expect(res.indexOf('+more')).to.be(-1); - }); + it('diff on file commit should work if file is changing', async () => { + const res = await common.get(req, '/gitlog', { path: testDir }).then((res) => { + expect(res.nodes.length).to.be(2); + return common.get(req, '/diff', { path: testDir, file: testFile, sha1: res.nodes[1].sha1 }); + }); + + expect(res.indexOf('diff --git a/afile.txt b/afile.txt')).to.be.above(-1); + expect(res.indexOf('+more')).to.be(-1); }); - it('getting current image file should work', () => { - return common - .getPng(req, '/diff/image', { path: testDir, filename: testImage, version: 'current' }) - .then((res) => expect(res.toString()).to.be('png ~~')); + it('getting current image file should work', async () => { + const res = await common.getPng(req, '/diff/image', { + path: testDir, + filename: testImage, + version: 'current', + }); + + return expect(res.toString()).to.be('png ~~'); }); - it('getting previous image file should work', () => { - return common - .getPng(req, '/diff/image', { path: testDir, filename: testImage, version: 'HEAD' }) - .then((res) => expect(res.toString()).to.be('png')); + it('getting previous image file should work', async () => { + const res = await common.getPng(req, '/diff/image', { + path: testDir, + filename: testImage, + version: 'HEAD', + }); + + return expect(res.toString()).to.be('png'); }); it('should be possible to rename a modified file', () => { @@ -154,13 +162,15 @@ describe('git-api diff', () => { }); }); - it('diff on renamed and modified file should work', () => { - return common - .get(req, '/diff', { path: testDir, file: testFile2, oldFile: testFile }) - .then((res) => { - expect(res.indexOf('diff --git a/afile.txt b/anotherfile.txt')).to.be.above(-1); - expect(res.indexOf('+more')).to.be.above(-1); - }); + it('diff on renamed and modified file should work', async () => { + const res = await common.get(req, '/diff', { + path: testDir, + file: testFile2, + oldFile: testFile, + }); + + expect(res.indexOf('diff --git a/afile.txt b/anotherfile.txt')).to.be.above(-1); + expect(res.indexOf('+more')).to.be.above(-1); }); it('should be possible to commit the renamed and modified file', () => { @@ -171,23 +181,20 @@ describe('git-api diff', () => { }); }); - it('diff on commit with renamed and modified file should work', () => { - return common - .get(req, '/gitlog', { path: testDir }) - .then((res) => { - expect(res.nodes.length).to.be(3); - return common.get(req, '/diff', { - path: testDir, - file: testFile2, - oldFile: testFile, - sha1: res.nodes[0].sha1, - }); - }) - .then((res) => { - for (let i = 0; i < content.length; i++) { - expect(res.indexOf(content[i])).to.be.above(-1); - } + it('diff on commit with renamed and modified file should work', async () => { + const res = await common.get(req, '/gitlog', { path: testDir }).then((res) => { + expect(res.nodes.length).to.be(3); + return common.get(req, '/diff', { + path: testDir, + file: testFile2, + oldFile: testFile, + sha1: res.nodes[0].sha1, }); + }); + + for (let i = 0; i < content.length; i++) { + expect(res.indexOf(content[i])).to.be.above(-1); + } }); it('removing a test file should work', () => { @@ -205,31 +212,33 @@ describe('git-api diff', () => { return common.post(req, '/testing/removefile', { file: path.join(testDir, testImage) }); }); - it('diff on removed file should work', () => { - return common.get(req, '/diff', { path: testDir, file: testFile2 }).then((res) => { - expect(res.indexOf('deleted file')).to.be.above(-1); - expect(res.indexOf('@@ -1,6 +0,0 @@')).to.be.above(-1); - }); + it('diff on removed file should work', async () => { + const res = await common.get(req, '/diff', { path: testDir, file: testFile2 }); + expect(res.indexOf('deleted file')).to.be.above(-1); + expect(res.indexOf('@@ -1,6 +0,0 @@')).to.be.above(-1); }); - it('getting previous image file should work', () => { - return common - .getPng(req, '/diff/image', { path: testDir, filename: testImage, version: 'HEAD' }) - .then((res) => expect(res.toString()).to.be('png ~~')); + it('getting previous image file should work', async () => { + const res = await common.getPng(req, '/diff/image', { + path: testDir, + filename: testImage, + version: 'HEAD', + }); + + return expect(res.toString()).to.be('png ~~'); }); - it('diff on bare repository file should work', () => { + it('diff on bare repository file should work', async () => { // first add remote and push all commits - return common + const res = await common .post(req, '/remotes/barerepository', { path: testDir, url: testBareDir }) .then(() => common.post(req, '/push', { path: testDir, remote: 'barerepository' })) - .then(() => common.get(req, '/gitlog', { path: testDir })) - .then((res) => { - // find a commit which contains the testFile - const commit = res.nodes.filter((commit) => - commit.fileLineDiffs.some((lineDiff) => lineDiff.fileName == testFile) - )[0]; - return common.get(req, '/diff', { path: testDir, sha1: commit.sha1, file: testFile }); - }); + .then(() => common.get(req, '/gitlog', { path: testDir })); + + // find a commit which contains the testFile + const commit = res.nodes.filter((commit) => + commit.fileLineDiffs.some((lineDiff) => lineDiff.fileName == testFile) + )[0]; + return common.get(req, '/diff', { path: testDir, sha1: commit.sha1, file: testFile }); }); }); diff --git a/test/spec.git-api.discardchanges.js b/test/spec.git-api.discardchanges.js index 87dbb6f6c..bbd09e52f 100644 --- a/test/spec.git-api.discardchanges.js +++ b/test/spec.git-api.discardchanges.js @@ -15,106 +15,105 @@ const req = request(app); describe('git-api discardchanges', () => { after(() => common.post(req, '/testing/cleanup')); - it('should be able to discard a new file', () => { - return common.createSmallRepo(req).then((dir) => { - const testFile1 = 'test.txt'; - return common - .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) - .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) - .then(() => common.get(req, '/status', { path: dir })) - .then((res) => expect(Object.keys(res.files).length).to.be(0)); - }); + it('should be able to discard a new file', async () => { + const dir = await common.createSmallRepo(req); + const testFile1 = 'test.txt'; + + const res = await common + .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) + .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) + .then(() => common.get(req, '/status', { path: dir })); + + return expect(Object.keys(res.files).length).to.be(0); }); - it('should be able to discard a changed file', () => { - return common.createSmallRepo(req).then((dir) => { - const testFile1 = 'test.txt'; + it('should be able to discard a changed file', async () => { + const dir = await common.createSmallRepo(req); + const testFile1 = 'test.txt'; - return common - .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) - .then(() => - common.post(req, '/commit', { path: dir, message: 'lol', files: [{ name: testFile1 }] }) - ) - .then(() => common.post(req, '/testing/changefile', { file: path.join(dir, testFile1) })) - .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) - .then(() => common.get(req, '/status', { path: dir })) - .then((res) => expect(Object.keys(res.files).length).to.be(0)); - }); + const res = await common + .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) + .then(() => + common.post(req, '/commit', { path: dir, message: 'lol', files: [{ name: testFile1 }] }) + ) + .then(() => common.post(req, '/testing/changefile', { file: path.join(dir, testFile1) })) + .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) + .then(() => common.get(req, '/status', { path: dir })); + + return expect(Object.keys(res.files).length).to.be(0); }); - it('should be able to discard a removed file', () => { - return common.createSmallRepo(req).then((dir) => { - const testFile1 = 'test.txt'; + it('should be able to discard a removed file', async () => { + const dir = await common.createSmallRepo(req); + const testFile1 = 'test.txt'; - return common - .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) - .then(() => - common.post(req, '/commit', { path: dir, message: 'lol', files: [{ name: testFile1 }] }) - ) - .then(() => common.post(req, '/testing/removefile', { file: path.join(dir, testFile1) })) - .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) - .then(() => common.get(req, '/status', { path: dir })) - .then((res) => expect(Object.keys(res.files).length).to.be(0)); - }); + const res = await common + .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) + .then(() => + common.post(req, '/commit', { path: dir, message: 'lol', files: [{ name: testFile1 }] }) + ) + .then(() => common.post(req, '/testing/removefile', { file: path.join(dir, testFile1) })) + .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) + .then(() => common.get(req, '/status', { path: dir })); + + return expect(Object.keys(res.files).length).to.be(0); }); - it('should be able to discard a new and staged file', () => { - return common.createSmallRepo(req).then((dir) => { - const testFile1 = 'test.txt'; + it('should be able to discard a new and staged file', async () => { + const dir = await common.createSmallRepo(req); + const testFile1 = 'test.txt'; - return common - .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) - .then(() => common.post(req, '/testing/git', { path: dir, command: ['add', testFile1] })) - .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) - .then(() => common.get(req, '/status', { path: dir })) - .then((res) => expect(Object.keys(res.files).length).to.be(0)); - }); + const res = await common + .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) + .then(() => common.post(req, '/testing/git', { path: dir, command: ['add', testFile1] })) + .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) + .then(() => common.get(req, '/status', { path: dir })); + + return expect(Object.keys(res.files).length).to.be(0); }); - it('should be able to discard a staged and removed file', () => { - return common.createSmallRepo(req).then((dir) => { - const testFile1 = 'test.txt'; + it('should be able to discard a staged and removed file', async () => { + const dir = await common.createSmallRepo(req); + const testFile1 = 'test.txt'; - return common - .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) - .then(() => common.post(req, '/testing/git', { path: dir, command: ['add', testFile1] })) - .then(() => common.post(req, '/testing/removefile', { file: path.join(dir, testFile1) })) - .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) - .then(() => common.get(req, '/status', { path: dir })) - .then((res) => expect(Object.keys(res.files).length).to.be(0)); - }); + const res = await common + .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) + .then(() => common.post(req, '/testing/git', { path: dir, command: ['add', testFile1] })) + .then(() => common.post(req, '/testing/removefile', { file: path.join(dir, testFile1) })) + .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) + .then(() => common.get(req, '/status', { path: dir })); + + return expect(Object.keys(res.files).length).to.be(0); }); - it('should be able to discard discard submodule changes', function () { + it('should be able to discard discard submodule changes', async function () { const testFile = 'smalltestfile.txt'; const submodulePath = 'subrepo'; this.timeout(5000); - return common - .createSmallRepo(req) - .then((dir) => { - return common.createSmallRepo(req).then((subrepoDir) => { - return common - .post(req, '/submodules/add', { - submoduleUrl: subrepoDir, - submodulePath: submodulePath, - path: dir, - }) - .then(() => dir); - }); - }) - .then((dir) => { - return common - .post(req, '/commit', { path: dir, message: 'lol', files: [{ name: '.gitmodules' }] }) - .then(() => - common.post(req, '/testing/changefile', { - file: path.join(dir, submodulePath, testFile), - }) - ) - .then(() => common.post(req, '/discardchanges', { path: dir, file: submodulePath })) - .then(() => common.get(req, '/status', { path: dir })) - .then((res) => expect(Object.keys(res.files).length).to.be(0)); + const dir = await common.createSmallRepo(req).then(async (dir) => { + const subrepoDir = await common.createSmallRepo(req); + + await common.post(req, '/submodules/add', { + submoduleUrl: subrepoDir, + submodulePath: submodulePath, + path: dir, }); + + return dir; + }); + + const res = await common + .post(req, '/commit', { path: dir, message: 'lol', files: [{ name: '.gitmodules' }] }) + .then(() => + common.post(req, '/testing/changefile', { + file: path.join(dir, submodulePath, testFile), + }) + ) + .then(() => common.post(req, '/discardchanges', { path: dir, file: submodulePath })) + .then(() => common.get(req, '/status', { path: dir })); + + return expect(Object.keys(res.files).length).to.be(0); }); // Need to make discardchanges even more powerful to handle this diff --git a/test/spec.git-api.ignorefile.js b/test/spec.git-api.ignorefile.js index da93250c8..6f90f3c7d 100644 --- a/test/spec.git-api.ignorefile.js +++ b/test/spec.git-api.ignorefile.js @@ -16,73 +16,61 @@ const req = request(app); describe('git-api: test ignorefile call', () => { after(() => common.post(req, '/testing/cleanup')); - it('Add a file to .gitignore file through api call', () => { - return common.createSmallRepo(req).then((dir) => { - const testFile = 'test.txt'; + it('Add a file to .gitignore file through api call', async () => { + const dir = await common.createSmallRepo(req); + const testFile = 'test.txt'; - // Create .gitignore file prior to append - return fs - .writeFile(path.join(dir, '.gitignore'), 'test git ignore file...') - .then(() => common.post(req, '/testing/createfile', { file: path.join(dir, testFile) })) - .then(() => common.post(req, '/ignorefile', { path: dir, file: testFile })) - .then(() => { - return common.get(req, '/status', { path: dir }).then((res) => { - expect(Object.keys(res.files).toString()).to.be('.gitignore'); - }); - }) - .then(() => { - return fs.readFile(path.join(dir, '.gitignore')).then((data) => { - if (data.toString().indexOf(testFile) < 0) { - throw new Error('Test file is not added to the .gitignore file.'); - } - }); - }); - }); + // Create .gitignore file prior to append + await fs + .writeFile(path.join(dir, '.gitignore'), 'test git ignore file...') + .then(() => common.post(req, '/testing/createfile', { file: path.join(dir, testFile) })) + .then(() => common.post(req, '/ignorefile', { path: dir, file: testFile })) + .then(async () => { + const res = await common.get(req, '/status', { path: dir }); + expect(Object.keys(res.files).toString()).to.be('.gitignore'); + }); + + const data = await fs.readFile(path.join(dir, '.gitignore')); + if (data.toString().indexOf(testFile) < 0) { + throw new Error('Test file is not added to the .gitignore file.'); + } }); - it('Add a file to .gitignore file through api call when .gitignore is missing', () => { - return common.createSmallRepo(req).then((dir) => { - const testFile = 'test.txt'; + it('Add a file to .gitignore file through api call when .gitignore is missing', async () => { + const dir = await common.createSmallRepo(req); + const testFile = 'test.txt'; + + await common + .post(req, '/testing/createfile', { file: path.join(dir, testFile) }) + .then(() => common.post(req, '/ignorefile', { path: dir, file: testFile })) + .then(async () => { + const res = await common.get(req, '/status', { path: dir }); + expect(Object.keys(res.files).toString()).to.be('.gitignore'); + }); - return common - .post(req, '/testing/createfile', { file: path.join(dir, testFile) }) - .then(() => common.post(req, '/ignorefile', { path: dir, file: testFile })) - .then(() => { - return common.get(req, '/status', { path: dir }).then((res) => { - expect(Object.keys(res.files).toString()).to.be('.gitignore'); - }); - }) - .then(() => { - return fs.readFile(path.join(dir, '.gitignore')).then((data) => { - if (data.toString().indexOf(testFile) < 0) { - throw new Error('Test file is not added to the .gitignore file.'); - } - }); - }); - }); + const data = await fs.readFile(path.join(dir, '.gitignore')); + if (data.toString().indexOf(testFile) < 0) { + throw new Error('Test file is not added to the .gitignore file.'); + } }); - it('Attempt to add a file where similar name alread exist in .gitignore through api call', () => { - return common.createSmallRepo(req).then((dir) => { - const testFile = 'test.txt'; + it('Attempt to add a file where similar name alread exist in .gitignore through api call', async () => { + const dir = await common.createSmallRepo(req); + const testFile = 'test.txt'; + + // add part of file name to gitignore + await fs + .appendFile(path.join(dir, '.gitignore'), testFile.split('.')[0]) + .then(() => common.post(req, '/testing/createfile', { file: path.join(dir, testFile) })) + .then(() => common.post(req, '/ignorefile', { path: dir, file: testFile })) + .then(async () => { + const res = await common.get(req, '/status', { path: dir }); + expect(Object.keys(res.files).toString()).to.be('.gitignore'); + }); - // add part of file name to gitignore - return fs - .appendFile(path.join(dir, '.gitignore'), testFile.split('.')[0]) - .then(() => common.post(req, '/testing/createfile', { file: path.join(dir, testFile) })) - .then(() => common.post(req, '/ignorefile', { path: dir, file: testFile })) - .then(() => { - return common.get(req, '/status', { path: dir }).then((res) => { - expect(Object.keys(res.files).toString()).to.be('.gitignore'); - }); - }) - .then(() => { - return fs.readFile(path.join(dir, '.gitignore')).then((data) => { - if (data.toString().indexOf(testFile) < 0) { - throw new Error('Test file is not added to the .gitignore file.'); - } - }); - }); - }); + const data = await fs.readFile(path.join(dir, '.gitignore')); + if (data.toString().indexOf(testFile) < 0) { + throw new Error('Test file is not added to the .gitignore file.'); + } }); }); diff --git a/test/spec.git-api.js b/test/spec.git-api.js index 3d9dfb9fa..7f144cb2c 100644 --- a/test/spec.git-api.js +++ b/test/spec.git-api.js @@ -18,24 +18,21 @@ let gitConfig; const req = request(app); describe('git-api', () => { - before('creating test dir should work', () => { - return common.post(req, '/testing/createtempdir').then((res) => { - expect(res.path).to.be.ok(); - return fs.realpath(res.path).then((dir) => { - testDir = dir; - }); - }); + before('creating test dir should work', async () => { + const res = await common.post(req, '/testing/createtempdir'); + expect(res.path).to.be.ok(); + const dir = await fs.realpath(res.path); + testDir = dir; }); after(() => common.post(req, '/testing/cleanup')); - it('gitconfig should return config data', () => { - return common.get(req, '/gitconfig', { path: testDir }).then((res) => { - expect(res).to.be.an('object'); - expect(res['user.name']).to.be.ok(); - expect(res['user.email']).to.be.ok(); - gitConfig = res; - }); + it('gitconfig should return config data', async () => { + const res = await common.get(req, '/gitconfig', { path: testDir }); + expect(res).to.be.an('object'); + expect(res['user.name']).to.be.ok(); + expect(res['user.email']).to.be.ok(); + gitConfig = res; }); it('status should fail in uninited directory', (done) => { @@ -51,10 +48,10 @@ describe('git-api', () => { }); }); - it('quickstatus should say uninited in uninited directory', () => { - return common - .get(req, '/quickstatus', { path: testDir }) - .then((res) => expect(res).to.eql({ type: 'uninited', gitRootPath: testDir })); + it('quickstatus should say uninited in uninited directory', async () => { + const res = await common.get(req, '/quickstatus', { path: testDir }); + + return expect(res).to.eql({ type: 'uninited', gitRootPath: testDir }); }); it('status should fail in non-existing directory', () => { @@ -63,12 +60,10 @@ describe('git-api', () => { .catch((e) => expect(e.errorCode).to.be('no-such-path')); }); - it('quickstatus should say false in non-existing directory', () => { - return common - .get(req, '/quickstatus', { path: path.join(testDir, 'nowhere') }) - .then((res) => - expect(res).to.eql({ type: 'no-such-path', gitRootPath: path.join(testDir, 'nowhere') }) - ); + it('quickstatus should say false in non-existing directory', async () => { + const res = await common.get(req, '/quickstatus', { path: path.join(testDir, 'nowhere') }); + + return expect(res).to.eql({ type: 'no-such-path', gitRootPath: path.join(testDir, 'nowhere') }); }); it('init should succeed in uninited directory', () => { @@ -79,10 +74,10 @@ describe('git-api', () => { return common.get(req, '/status', { path: testDir }); }); - it('quickstatus should say inited in inited directory', () => { - return common - .get(req, '/quickstatus', { path: testDir }) - .then((res) => expect(res).to.eql({ type: 'inited', gitRootPath: testDir })); + it('quickstatus should say inited in inited directory', async () => { + const res = await common.get(req, '/quickstatus', { path: testDir }); + + return expect(res).to.eql({ type: 'inited', gitRootPath: testDir }); }); it("commit should fail on when there's no files to commit", (done) => { @@ -97,18 +92,16 @@ describe('git-api', () => { const testFile = 'somefile'; - it('log should be empty before first commit', () => { - return common.get(req, '/gitlog', { path: testDir }).then((res) => { - expect(res.nodes).to.be.a('array'); - expect(res.nodes.length).to.be(0); - }); + it('log should be empty before first commit', async () => { + const res = await common.get(req, '/gitlog', { path: testDir }); + expect(res.nodes).to.be.a('array'); + expect(res.nodes.length).to.be(0); }); - it('head should be empty before first commit', () => { - return common.get(req, '/head', { path: testDir }).then((res) => { - expect(res).to.be.a('array'); - expect(res.length).to.be(0); - }); + it('head should be empty before first commit', async () => { + const res = await common.get(req, '/head', { path: testDir }); + expect(res).to.be.a('array'); + expect(res.length).to.be(0); }); it('commit should fail on non-existing file', (done) => { @@ -125,22 +118,21 @@ describe('git-api', () => { return common.post(req, '/testing/createfile', { file: path.join(testDir, testFile) }); }); - it('status should list untracked file', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile]).to.eql({ - displayName: testFile, - fileName: testFile, - oldFileName: testFile, - isNew: true, - staged: false, - removed: false, - conflict: false, - renamed: false, - type: 'text', - additions: '-', - deletions: '-', - }); + it('status should list untracked file', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile]).to.eql({ + displayName: testFile, + fileName: testFile, + oldFileName: testFile, + isNew: true, + staged: false, + removed: false, + conflict: false, + renamed: false, + type: 'text', + additions: '-', + deletions: '-', }); }); @@ -164,46 +156,43 @@ describe('git-api', () => { }); }); - it('log should show latest commit', () => { - return common.get(req, '/gitlog', { path: testDir }).then((res) => { - expect(res.nodes).to.be.a('array'); - expect(res.nodes.length).to.be(1); - expect(res.nodes[0].message.indexOf(commitMessage)).to.be(0); - expect(res.nodes[0].authorName).to.be(gitConfig['user.name']); - expect(res.nodes[0].authorEmail).to.be(gitConfig['user.email']); - }); + it('log should show latest commit', async () => { + const res = await common.get(req, '/gitlog', { path: testDir }); + expect(res.nodes).to.be.a('array'); + expect(res.nodes.length).to.be(1); + expect(res.nodes[0].message.indexOf(commitMessage)).to.be(0); + expect(res.nodes[0].authorName).to.be(gitConfig['user.name']); + expect(res.nodes[0].authorEmail).to.be(gitConfig['user.email']); }); - it('head should show latest commit', () => { - return common.get(req, '/head', { path: testDir }).then((res) => { - expect(res).to.be.a('array'); - expect(res.length).to.be(1); - expect(res[0].message.indexOf(commitMessage)).to.be(0); - expect(res[0].authorName).to.be(gitConfig['user.name']); - expect(res[0].authorEmail).to.be(gitConfig['user.email']); - }); + it('head should show latest commit', async () => { + const res = await common.get(req, '/head', { path: testDir }); + expect(res).to.be.a('array'); + expect(res.length).to.be(1); + expect(res[0].message.indexOf(commitMessage)).to.be(0); + expect(res[0].authorName).to.be(gitConfig['user.name']); + expect(res[0].authorEmail).to.be(gitConfig['user.email']); }); it('modifying a test file should work', () => { return common.post(req, '/testing/changefile', { file: path.join(testDir, testFile) }); }); - it('modified file should show up in status', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile]).to.eql({ - displayName: testFile, - fileName: testFile, - oldFileName: testFile, - isNew: false, - staged: false, - removed: false, - conflict: false, - renamed: false, - type: 'text', - additions: '1', - deletions: '1', - }); + it('modified file should show up in status', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile]).to.eql({ + displayName: testFile, + fileName: testFile, + oldFileName: testFile, + isNew: false, + staged: false, + removed: false, + conflict: false, + renamed: false, + type: 'text', + additions: '1', + deletions: '1', }); }); @@ -224,10 +213,10 @@ describe('git-api', () => { }); }); - it('amend should not produce additional log-entry', () => { - return common - .get(req, '/gitlog', { path: testDir }) - .then((res) => expect(res.nodes.length).to.be(1)); + it('amend should not produce additional log-entry', async () => { + const res = await common.get(req, '/gitlog', { path: testDir }); + + return expect(res.nodes.length).to.be(1); }); const testFile2 = 'my test.txt'; @@ -236,22 +225,21 @@ describe('git-api', () => { return common.post(req, '/testing/createfile', { file: path.join(testDir, testFile2) }); }); - it('status should list the new file', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile2]).to.eql({ - displayName: testFile2, - fileName: testFile2, - oldFileName: testFile2, - isNew: true, - staged: false, - removed: false, - conflict: false, - renamed: false, - type: 'text', - additions: '-', - deletions: '-', - }); + it('status should list the new file', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile2]).to.eql({ + displayName: testFile2, + fileName: testFile2, + oldFileName: testFile2, + isNew: true, + staged: false, + removed: false, + conflict: false, + renamed: false, + type: 'text', + additions: '-', + deletions: '-', }); }); @@ -283,22 +271,21 @@ describe('git-api', () => { return common.post(req, '/testing/createfile', { file: path.join(testDir, testFile3) }); }); - it('status should list the new file', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile3]).to.eql({ - displayName: testFile3, - fileName: testFile3, - oldFileName: testFile3, - isNew: true, - staged: false, - removed: false, - conflict: false, - renamed: false, - type: 'text', - additions: '-', - deletions: '-', - }); + it('status should list the new file', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile3]).to.eql({ + displayName: testFile3, + fileName: testFile3, + oldFileName: testFile3, + isNew: true, + staged: false, + removed: false, + conflict: false, + renamed: false, + type: 'text', + additions: '-', + deletions: '-', }); }); @@ -312,43 +299,41 @@ describe('git-api', () => { }); }); - it('log should show last commit', () => { - return common.get(req, '/gitlog', { path: testDir }).then((res) => { - expect(res.nodes).to.be.a('array'); - expect(res.nodes.length).to.be(2); - const HEAD = res.nodes[0]; - - expect(HEAD.message.indexOf(commitMessage3)).to.be(0); - expect(HEAD.authorDate).to.be.a('string'); - expect(HEAD.authorName).to.be(gitConfig['user.name']); - expect(HEAD.authorEmail).to.be(gitConfig['user.email']); - expect(HEAD.commitDate).to.be.a('string'); - expect(HEAD.committerName).to.be(gitConfig['user.name']); - expect(HEAD.committerEmail).to.be(gitConfig['user.email']); - expect(HEAD.sha1).to.be.ok(); - }); + it('log should show last commit', async () => { + const res = await common.get(req, '/gitlog', { path: testDir }); + expect(res.nodes).to.be.a('array'); + expect(res.nodes.length).to.be(2); + const HEAD = res.nodes[0]; + + expect(HEAD.message.indexOf(commitMessage3)).to.be(0); + expect(HEAD.authorDate).to.be.a('string'); + expect(HEAD.authorName).to.be(gitConfig['user.name']); + expect(HEAD.authorEmail).to.be(gitConfig['user.email']); + expect(HEAD.commitDate).to.be.a('string'); + expect(HEAD.committerName).to.be(gitConfig['user.name']); + expect(HEAD.committerEmail).to.be(gitConfig['user.email']); + expect(HEAD.sha1).to.be.ok(); }); it('removing a test file should work', () => { return common.post(req, '/testing/removefile', { file: path.join(testDir, testFile) }); }); - it('status should list the removed file', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile]).to.eql({ - displayName: testFile, - fileName: testFile, - oldFileName: testFile, - isNew: false, - staged: false, - removed: true, - conflict: false, - renamed: false, - type: 'text', - additions: '0', - deletions: '2', - }); + it('status should list the removed file', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile]).to.eql({ + displayName: testFile, + fileName: testFile, + oldFileName: testFile, + isNew: false, + staged: false, + removed: true, + conflict: false, + renamed: false, + type: 'text', + additions: '0', + deletions: '2', }); }); @@ -362,10 +347,10 @@ describe('git-api', () => { }); }); - it('status should list nothing', () => { - return common - .get(req, '/status', { path: testDir }) - .then((res) => expect(Object.keys(res.files).length).to.be(0)); + it('status should list nothing', async () => { + const res = await common.get(req, '/status', { path: testDir }); + + return expect(Object.keys(res.files).length).to.be(0); }); const testFile4 = path.join(testSubDir, 'renamed.txt').replace(/\\/, '/'); @@ -377,51 +362,49 @@ describe('git-api', () => { }); }); - it('status should list the renamed file', () => { - return common.get(req, '/status', { path: testDir }).then((res) => { - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[testFile4]).to.eql({ - displayName: `${testFile3} → ${testFile4}`, - fileName: testFile4, - oldFileName: testFile3, - isNew: false, - staged: false, - removed: false, - conflict: false, - renamed: true, - type: 'text', - additions: '0', - deletions: '0', - }); + it('status should list the renamed file', async () => { + const res = await common.get(req, '/status', { path: testDir }); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[testFile4]).to.eql({ + displayName: `${testFile3} → ${testFile4}`, + fileName: testFile4, + oldFileName: testFile3, + isNew: false, + staged: false, + removed: false, + conflict: false, + renamed: true, + type: 'text', + additions: '0', + deletions: '0', }); }); - it('log with limit should only return specified number of items', () => { - return common.get(req, '/gitlog', { path: testDir, limit: 1 }).then((res) => { - expect(res.nodes).to.be.a('array'); - expect(res.nodes.length).to.be(1); - }); + it('log with limit should only return specified number of items', async () => { + const res = await common.get(req, '/gitlog', { path: testDir, limit: 1 }); + expect(res.nodes).to.be.a('array'); + expect(res.nodes.length).to.be(1); }); it('get the baserepopath without base repo should work', (done) => { const baseRepoPathTestDir = path.join(testDir, 'depth1', 'depth2'); - mkdirp(baseRepoPathTestDir).then(() => { - return common.get(req, '/baserepopath', { path: baseRepoPathTestDir }).then((res) => { - // Some oses uses symlink and path will be different as git will return resolved symlink - expect(res.path).to.contain(testDir); - done(); - }); + mkdirp(baseRepoPathTestDir).then(async () => { + const res = await common.get(req, '/baserepopath', { path: baseRepoPathTestDir }); + // Some oses uses symlink and path will be different as git will return resolved symlink + expect(res.path).to.contain(testDir); + done(); }); }); - it('test gitignore api endpoint', () => { - return common + it('test gitignore api endpoint', async () => { + const res = await common .put(req, '/gitignore', { path: testDir, data: 'abc' }) .then(() => common.get(req, '/gitignore', { path: testDir })) .then((res) => expect(res.content).to.be('abc')) .then(() => common.put(req, '/gitignore', { path: testDir, data: '' })) - .then(() => common.get(req, '/gitignore', { path: testDir })) - .then((res) => expect(res.content).to.be('')); + .then(() => common.get(req, '/gitignore', { path: testDir })); + + return expect(res.content).to.be(''); }); }); diff --git a/test/spec.git-api.patch.js b/test/spec.git-api.patch.js index 0eef89850..99ebb7761 100644 --- a/test/spec.git-api.patch.js +++ b/test/spec.git-api.patch.js @@ -14,9 +14,9 @@ restGit.registerApi({ app: app, config: { dev: true } }); let testDir; const req = request(app); -const testPatch = (req, testDir, testFileName, contentsToPatch, files) => { +const testPatch = async (req, testDir, testFileName, contentsToPatch, files) => { // testDir = '/tmp/testdir'; - return common + await common .post(req, '/testing/createfile', { file: path.join(testDir, testFileName), content: contentsToPatch[0], @@ -33,14 +33,13 @@ const testPatch = (req, testDir, testFileName, contentsToPatch, files) => { file: path.join(testDir, testFileName), content: contentsToPatch[1], }) - ) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: `patched commit ${testFileName}`, - files: files, - }) ); + + return common.post(req, '/commit', { + path: testDir, + message: `patched commit ${testFileName}`, + files: files, + }); }; const getPatchLineList = (size, notSelected) => { @@ -108,11 +107,10 @@ const getContentsToPatchWithDelete = (size, numLinesToDelete) => { }; describe('git-api: test patch api', () => { - it('creating test dir should work', () => { - return common.post(req, '/testing/createtempdir').then((res) => { - expect(res.path).to.be.ok(); - testDir = res.path; - }); + it('creating test dir should work', async () => { + const res = await common.post(req, '/testing/createtempdir'); + expect(res.path).to.be.ok(); + testDir = res.path; }); it('init test dir should work', () => { diff --git a/test/spec.git-api.remote.js b/test/spec.git-api.remote.js index 1b55cff98..29404845f 100644 --- a/test/spec.git-api.remote.js +++ b/test/spec.git-api.remote.js @@ -18,8 +18,8 @@ const req = request(app); describe('git-api remote', function () { this.timeout(4000); - before('creating test dirs should work', () => { - return common + before('creating test dirs should work', async () => { + const dir = await common .post(req, '/testing/createtempdir') .then((dir) => { testDirLocal1 = dir.path; @@ -28,10 +28,9 @@ describe('git-api remote', function () { .then((dir) => { testDirLocal2 = dir.path; }) - .then(() => common.post(req, '/testing/createtempdir')) - .then((dir) => { - testDirRemote = dir.path; - }); + .then(() => common.post(req, '/testing/createtempdir')); + + testDirRemote = dir.path; }); after(() => common.post(req, '/testing/cleanup')); @@ -40,10 +39,10 @@ describe('git-api remote', function () { return common.post(req, '/init', { path: testDirRemote, bare: true }); }); - it('remotes in no-remotes-repo should be zero', () => { - return common - .get(req, '/remotes', { path: testDirRemote }) - .then((res) => expect(res.length).to.be(0)); + it('remotes in no-remotes-repo should be zero', async () => { + const res = await common.get(req, '/remotes', { path: testDirRemote }); + + return expect(res.length).to.be(0); }); it('cloning "remote" to "local1" should work', () => { @@ -54,39 +53,36 @@ describe('git-api remote', function () { }); }); - it('remotes in cloned-repo should be one', () => { - return common.get(req, '/remotes', { path: testDirLocal1 }).then((res) => { - expect(res.length).to.be(1); - expect(res[0]).to.be('origin'); - }); + it('remotes in cloned-repo should be one', async () => { + const res = await common.get(req, '/remotes', { path: testDirLocal1 }); + expect(res.length).to.be(1); + expect(res[0]).to.be('origin'); }); - it('remote/origin in cloned-repo should work', () => { - return common - .get(req, '/remotes/origin', { path: testDirLocal1 }) - .then((res) => expect(res.address).to.be(testDirRemote)); + it('remote/origin in cloned-repo should work', async () => { + const res = await common.get(req, '/remotes/origin', { path: testDirLocal1 }); + + return expect(res.address).to.be(testDirRemote); }); - it('creating a commit in "local1" repo should work', () => { + it('creating a commit in "local1" repo should work', async () => { const testFile = path.join(testDirLocal1, 'testfile1.txt'); - return common.post(req, '/testing/createfile', { file: testFile }).then(() => { - return common.post(req, '/commit', { - path: testDirLocal1, - message: 'Init', - files: [{ name: testFile }], - }); + await common.post(req, '/testing/createfile', { file: testFile }); + return common.post(req, '/commit', { + path: testDirLocal1, + message: 'Init', + files: [{ name: testFile }], }); }); - it('log in "local1" should show the init commit', () => { - return common.get(req, '/gitlog', { path: testDirLocal1 }).then((res) => { - expect(res.nodes).to.be.a('array'); - expect(res.nodes.length).to.be(1); - const init = res.nodes[0]; - expect(init.message.indexOf('Init')).to.be(0); - expect(init.refs).to.contain('HEAD'); - expect(init.refs).to.contain('refs/heads/master'); - }); + it('log in "local1" should show the init commit', async () => { + const res = await common.get(req, '/gitlog', { path: testDirLocal1 }); + expect(res.nodes).to.be.a('array'); + expect(res.nodes.length).to.be(1); + const init = res.nodes[0]; + expect(init.message.indexOf('Init')).to.be(0); + expect(init.refs).to.contain('HEAD'); + expect(init.refs).to.contain('refs/heads/master'); }); it('pushing form "local1" to "remote" should work', () => { @@ -115,9 +111,10 @@ describe('git-api remote', function () { }); }); - it('creating and pushing a commit in "local1" repo should work', () => { + it('creating and pushing a commit in "local1" repo should work', async () => { const testFile = path.join(testDirLocal1, 'testfile2.txt'); - return common + + await common .post(req, '/testing/createfile', { file: testFile }) .then(() => new Promise((resolve) => setTimeout(resolve, 500))) .then(() => @@ -126,8 +123,9 @@ describe('git-api remote', function () { message: 'Commit2', files: [{ name: testFile }], }) - ) - .then(() => common.post(req, '/push', { path: testDirLocal1, remote: 'origin' })); + ); + + return common.post(req, '/push', { path: testDirLocal1, remote: 'origin' }); }); it('fetching in "local2" should work', () => { @@ -169,18 +167,18 @@ describe('git-api remote', function () { }); }); - it('creating a commit in "local2" repo should work', () => { + it('creating a commit in "local2" repo should work', async () => { const testFile = path.join(testDirLocal2, 'testfile3.txt'); - return common + + await common .post(req, '/testing/createfile', { file: testFile }) - .then(() => new Promise((resolve) => setTimeout(resolve, 500))) - .then(() => - common.post(req, '/commit', { - path: testDirLocal2, - message: 'Commit3', - files: [{ name: testFile }], - }) - ); + .then(() => new Promise((resolve) => setTimeout(resolve, 500))); + + return common.post(req, '/commit', { + path: testDirLocal2, + message: 'Commit3', + files: [{ name: testFile }], + }); }); it('resetting local master to remote master should work in "local2"', () => { @@ -200,10 +198,10 @@ describe('git-api remote', function () { }); }); - it('status should show nothing', () => { - return common - .get(req, '/status', { path: testDirLocal2 }) - .then((res) => expect(Object.keys(res.files).length).to.be(0)); + it('status should show nothing', async () => { + const res = await common.get(req, '/status', { path: testDirLocal2 }); + + return expect(Object.keys(res.files).length).to.be(0); }); it('should be possible to create a tag in "local2"', () => { @@ -219,16 +217,15 @@ describe('git-api remote', function () { }); }); - it('log in "local2" should show the local tag', () => { - return common.get(req, '/gitlog', { path: testDirLocal2 }).then((res) => { - const commit2 = _.find(res.nodes, (node) => node.message.indexOf('Commit2') == 0); - expect(commit2.refs).to.contain('tag: refs/tags/v1.0'); - }); + it('log in "local2" should show the local tag', async () => { + const res = await common.get(req, '/gitlog', { path: testDirLocal2 }); + const commit2 = _.find(res.nodes, (node) => node.message.indexOf('Commit2') == 0); + expect(commit2.refs).to.contain('tag: refs/tags/v1.0'); }); - it('remote tags in "local2" should show the remote tag', () => { - return common - .get(req, '/remote/tags', { path: testDirLocal2, remote: 'origin' }) - .then((res) => expect(res.map((tag) => tag.name)).to.contain('refs/tags/v1.0^{}')); + it('remote tags in "local2" should show the remote tag', async () => { + const res = await common.get(req, '/remote/tags', { path: testDirLocal2, remote: 'origin' }); + + return expect(res.map((tag) => tag.name)).to.contain('refs/tags/v1.0^{}'); }); }); diff --git a/test/spec.git-api.squash.js b/test/spec.git-api.squash.js index 6a8cd3d34..57c8058eb 100644 --- a/test/spec.git-api.squash.js +++ b/test/spec.git-api.squash.js @@ -23,10 +23,9 @@ const testFile2 = 'testFile2.txt'; describe('git-api conflict rebase', function () { this.timeout(8000); - before(() => { - return common.createSmallRepo(req).then((dir) => { - testDir = dir; - }); + before(async () => { + const dir = await common.createSmallRepo(req); + testDir = dir; }); after(() => common.post(req, '/testing/cleanup')); @@ -35,8 +34,8 @@ describe('git-api conflict rebase', function () { return common.post(req, '/branches', { path: testDir, name: rootBranch, startPoint: 'master' }); }); - it('create some commits', () => { - return common + it('create some commits', async () => { + await common .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) .then(() => common.post(req, '/commit', { @@ -45,53 +44,51 @@ describe('git-api conflict rebase', function () { files: [{ name: testFile1 }], }) ) - .then(() => common.post(req, '/testing/createfile', { file: path.join(testDir, testFile2) })) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: `a commit for ${testFile2}`, - files: [{ name: testFile2 }], - }) - ); + .then(() => common.post(req, '/testing/createfile', { file: path.join(testDir, testFile2) })); + + return common.post(req, '/commit', { + path: testDir, + message: `a commit for ${testFile2}`, + files: [{ name: testFile2 }], + }); }); it('checkout master', () => { return common.post(req, '/checkout', { path: testDir, name: rootBranch }); }); - it('squash 2 commits to 1', () => { - return common + it('squash 2 commits to 1', async () => { + const res = await common .post(req, '/squash', { path: testDir, target: 'master' }) - .then(() => common.get(req, '/status', { path: testDir })) - .then((res) => expect(Object.keys(res.files).length).to.be(2)); + .then(() => common.get(req, '/status', { path: testDir })); + + return expect(Object.keys(res.files).length).to.be(2); }); - it('discard all', () => { - return common + it('discard all', async () => { + const res = await common .post(req, '/discardchanges', { path: testDir, all: true }) - .then(() => common.get(req, '/status', { path: testDir })) - .then((res) => expect(Object.keys(res.files).length).to.be(0)); + .then(() => common.get(req, '/status', { path: testDir })); + + return expect(Object.keys(res.files).length).to.be(0); }); - it('making conflicting commit', () => { - return common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: `a 2nd commit for ${testFile1}`, - files: [{ name: testFile1 }], - }) - ); + it('making conflicting commit', async () => { + await common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }); + + return common.post(req, '/commit', { + path: testDir, + message: `a 2nd commit for ${testFile1}`, + files: [{ name: testFile1 }], + }); }); - it('squash 2 commits to 1 with conflict', () => { - return common + it('squash 2 commits to 1 with conflict', async () => { + const res = await common .post(req, '/squash', { path: testDir, target: 'master' }) - .then(() => common.get(req, '/status', { path: testDir })) - .then((res) => { - expect(res.inConflict).to.be(true); - expect(Object.keys(res.files).length).to.be(2); - }); + .then(() => common.get(req, '/status', { path: testDir })); + + expect(res.inConflict).to.be(true); + expect(Object.keys(res.files).length).to.be(2); }); }); diff --git a/test/spec.git-api.stash.js b/test/spec.git-api.stash.js index aa86f727c..7bf1df823 100644 --- a/test/spec.git-api.stash.js +++ b/test/spec.git-api.stash.js @@ -19,25 +19,23 @@ describe('git-api conflict rebase', function () { const testFile1 = 'testfile1.txt'; - before(() => { - return common - .createSmallRepo(req) - .then((dir) => { - testDir = dir; - }) - .then(() => common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) })); + before(async () => { + await common.createSmallRepo(req).then((dir) => { + testDir = dir; + }); + + return common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }); }); after(() => common.post(req, '/testing/cleanup')); it('should be possible to stash', () => common.post(req, '/stashes', { path: testDir })); - it('stashes should list the stashed item', () => { - return common.get(req, '/stashes', { path: testDir }).then((res) => { - expect(res.length).to.be(1); - expect(res[0].reflogId).to.be('0'); - expect(res[0].reflogName).to.be('stash@{0}'); - }); + it('stashes should list the stashed item', async () => { + const res = await common.get(req, '/stashes', { path: testDir }); + expect(res.length).to.be(1); + expect(res[0].reflogId).to.be('0'); + expect(res[0].reflogName).to.be('stash@{0}'); }); it('should be possible to drop stash', () => { diff --git a/test/spec.git-api.submodule.js b/test/spec.git-api.submodule.js index 764543df7..08dcd434a 100644 --- a/test/spec.git-api.submodule.js +++ b/test/spec.git-api.submodule.js @@ -17,16 +17,15 @@ describe('git-api submodule', function () { let testDirMain, testDirSecondary; - before(() => { - return common + before(async () => { + const dir = await common .createSmallRepo(req) .then((dir) => { testDirMain = dir; }) - .then(() => common.createSmallRepo(req)) - .then((dir) => { - testDirSecondary = dir; - }); + .then(() => common.createSmallRepo(req)); + + testDirSecondary = dir; }); after(() => common.post(req, '/testing/cleanup')); @@ -41,35 +40,34 @@ describe('git-api submodule', function () { }); }); - it('submodule should show up in status', () => { - return common.get(req, '/status', { path: testDirMain }).then((res) => { - expect(Object.keys(res.files).length).to.be(2); - expect(res.files[submodulePath]).to.eql({ - displayName: submodulePath, - fileName: submodulePath, - oldFileName: submodulePath, - isNew: true, - staged: true, - removed: false, - conflict: false, - renamed: false, - type: 'text', - additions: '1', - deletions: '0', - }); - expect(res.files['.gitmodules']).to.eql({ - displayName: '.gitmodules', - fileName: '.gitmodules', - oldFileName: '.gitmodules', - isNew: true, - staged: true, - removed: false, - conflict: false, - renamed: false, - type: 'text', - additions: '3', - deletions: '0', - }); + it('submodule should show up in status', async () => { + const res = await common.get(req, '/status', { path: testDirMain }); + expect(Object.keys(res.files).length).to.be(2); + expect(res.files[submodulePath]).to.eql({ + displayName: submodulePath, + fileName: submodulePath, + oldFileName: submodulePath, + isNew: true, + staged: true, + removed: false, + conflict: false, + renamed: false, + type: 'text', + additions: '1', + deletions: '0', + }); + expect(res.files['.gitmodules']).to.eql({ + displayName: '.gitmodules', + fileName: '.gitmodules', + oldFileName: '.gitmodules', + isNew: true, + staged: true, + removed: false, + conflict: false, + renamed: false, + type: 'text', + additions: '3', + deletions: '0', }); }); @@ -81,10 +79,10 @@ describe('git-api submodule', function () { }); }); - it('status should be empty after commit', () => { - return common - .get(req, '/status', { path: testDirMain }) - .then((res) => expect(Object.keys(res.files).length).to.be(0)); + it('status should be empty after commit', async () => { + const res = await common.get(req, '/status', { path: testDirMain }); + + return expect(Object.keys(res.files).length).to.be(0); }); it('creating a test file in sub dir should work', () => { @@ -92,29 +90,27 @@ describe('git-api submodule', function () { return common.post(req, '/testing/createfile', { file: path.join(testDirMain, testFile) }); }); - it("submodule should show up in status when it's dirty", () => { - return common.get(req, '/status', { path: testDirMain }).then((res) => { - expect(Object.keys(res.files).length).to.be(1); - expect(res.files[submodulePath]).to.eql({ - displayName: submodulePath, - fileName: submodulePath, - oldFileName: submodulePath, - isNew: false, - staged: false, - removed: false, - conflict: false, - renamed: false, - type: 'text', - additions: '0', - deletions: '0', - }); + it("submodule should show up in status when it's dirty", async () => { + const res = await common.get(req, '/status', { path: testDirMain }); + expect(Object.keys(res.files).length).to.be(1); + expect(res.files[submodulePath]).to.eql({ + displayName: submodulePath, + fileName: submodulePath, + oldFileName: submodulePath, + isNew: false, + staged: false, + removed: false, + conflict: false, + renamed: false, + type: 'text', + additions: '0', + deletions: '0', }); }); - it('diff on submodule should work', () => { - return common.get(req, '/diff', { path: testDirMain, file: submodulePath }).then((res) => { - expect(res.indexOf('-Subproject commit')).to.be.above(-1); - expect(res.indexOf('+Subproject commit')).to.be.above(-1); - }); + it('diff on submodule should work', async () => { + const res = await common.get(req, '/diff', { path: testDirMain, file: submodulePath }); + expect(res.indexOf('-Subproject commit')).to.be.above(-1); + expect(res.indexOf('+Subproject commit')).to.be.above(-1); }); }); From 885a8b2a106360b7dd4ccca9549cdb4d4fe4610b Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Mon, 11 May 2020 15:33:40 +0200 Subject: [PATCH 2/7] Promise chains => await Result of running the await-promise-chain.js codemod from https://github.com/sgilroy/async-await-codemod --- components/graph/git-ref.js | 41 +++--- source/server.js | 11 +- source/ungit-plugin.js | 6 +- test/common-es6.js | 6 +- test/spec.cache.js | 92 +++++--------- test/spec.git-api.branching.js | 10 +- test/spec.git-api.conflict-no-auto-stash.js | 19 +-- test/spec.git-api.conflict.js | 134 ++++++++++---------- test/spec.git-api.diff.js | 49 +++---- test/spec.git-api.discardchanges.js | 100 ++++++++------- test/spec.git-api.ignorefile.js | 44 +++---- test/spec.git-api.js | 12 +- test/spec.git-api.patch.js | 33 +++-- test/spec.git-api.remote.js | 41 +++--- test/spec.git-api.squash.js | 37 +++--- test/spec.git-api.stash.js | 5 +- test/spec.git-api.submodule.js | 10 +- 17 files changed, 309 insertions(+), 341 deletions(-) diff --git a/components/graph/git-ref.js b/components/graph/git-ref.js index cee9e196f..0fa75a29d 100644 --- a/components/graph/git-ref.js +++ b/components/graph/git-ref.js @@ -247,29 +247,26 @@ class RefViewModel extends Selectable { const isLocalCurrent = this.getLocalRef() && this.getLocalRef().current(); try { - await Promise.resolve() - .then(() => { - if (isRemote && !isLocalCurrent) { - return this.server.postPromise('/branches', { - path: this.graph.repoPath(), - name: this.refName, - sha1: this.name, - force: true, - }); - } - }) - .then(() => - this.server.postPromise('/checkout', { path: this.graph.repoPath(), name: this.refName }) - ) - .then(() => { - if (isRemote && isLocalCurrent) { - return this.server.postPromise('/reset', { - path: this.graph.repoPath(), - to: this.name, - mode: 'hard', - }); - } + await Promise.resolve(); + if (isRemote && !isLocalCurrent) { + return this.server.postPromise('/branches', { + path: this.graph.repoPath(), + name: this.refName, + sha1: this.name, + force: true, + }); + } + await this.server.postPromise('/checkout', { + path: this.graph.repoPath(), + name: this.refName, + }); + if (isRemote && isLocalCurrent) { + return this.server.postPromise('/reset', { + path: this.graph.repoPath(), + to: this.name, + mode: 'hard', }); + } this.graph.HEADref().node(this.node()); } catch (err) { diff --git a/source/server.js b/source/server.js index 8b2626ffe..8544878a7 100644 --- a/source/server.js +++ b/source/server.js @@ -294,13 +294,12 @@ const loadPlugins = async (plugins, pluginBasePath) => { const pluginsCacheKey = cache.registerFunc(async () => { const plugins = []; - await loadPlugins(plugins, path.join(__dirname, '..', 'components')).then(async () => { - try { - await fs.access(config.pluginDirectory); + await loadPlugins(plugins, path.join(__dirname, '..', 'components')); + try { + await fs.access(config.pluginDirectory); - return loadPlugins(plugins, config.pluginDirectory); - } catch (error) {} - }); + return loadPlugins(plugins, config.pluginDirectory); + } catch (error) {} return plugins; }); diff --git a/source/ungit-plugin.js b/source/ungit-plugin.js index 234665155..c5338ba8f 100644 --- a/source/ungit-plugin.js +++ b/source/ungit-plugin.js @@ -89,10 +89,10 @@ class UngitPlugin { return result; } }) - .then((result) => { + .then((result2) => { if (exports.css) { return ( - result + + result2 + assureArray(exports.css) .map((cssSource) => { return ``; @@ -100,7 +100,7 @@ class UngitPlugin { .join('\n') ); } else { - return result; + return result2; } }); diff --git a/test/common-es6.js b/test/common-es6.js index a6f1927ae..e7cd002e3 100644 --- a/test/common-es6.js +++ b/test/common-es6.js @@ -61,9 +61,9 @@ exports.createSmallRepo = async (req) => { const dir = await this.initRepo(req); const testFile = 'smalltestfile.txt'; - await this.post(req, '/testing/createfile', { file: path.join(dir, testFile) }).then(() => - this.post(req, '/commit', { path: dir, message: 'Init', files: [{ name: testFile }] }) - ); + await this.post(req, '/testing/createfile', { file: path.join(dir, testFile) }); + + await this.post(req, '/commit', { path: dir, message: 'Init', files: [{ name: testFile }] }); return dir; }; diff --git a/test/spec.cache.js b/test/spec.cache.js index 568749ca0..72d440c34 100644 --- a/test/spec.cache.js +++ b/test/spec.cache.js @@ -6,12 +6,11 @@ describe('cache', () => { let i = 0; const key = cache.registerFunc(() => i++); - const val = await cache - .resolveFunc(key) - .then((val) => { - expect(val).to.be(0); - }) - .then(() => cache.resolveFunc(key)); + const val2 = await cache.resolveFunc(key); + + expect(val2).to.be(0); + + const val = await cache.resolveFunc(key); return expect(val).to.be(0); }); @@ -48,15 +47,12 @@ describe('cache', () => { let i = 0; const key = cache.registerFunc(() => i++); - const val = await cache - .resolveFunc(key) - .then((val) => { - expect(val).to.be(0); - }) - .then(() => { - cache.invalidateFunc(key); - return cache.resolveFunc(key); - }); + const val2 = await cache.resolveFunc(key); + + expect(val2).to.be(0); + cache.invalidateFunc(key); + + const val = await cache.resolveFunc(key); expect(val).to.be(1); }); @@ -69,27 +65,18 @@ describe('cache', () => { cache.registerFunc(key1, func); cache.registerFunc(key2, func); - const val = await cache - .resolveFunc(key1) - .then((val) => { - expect(val).to.be(0); - }) - .then(() => cache.resolveFunc(key1)) - .then((val) => { - expect(val).to.be(0); - }) - .then(() => cache.resolveFunc(key2)) - .then((val) => { - expect(val).to.be(1); - }) - .then(() => { - cache.invalidateFunc(key1); - return cache.resolveFunc(key1); - }) - .then((val) => { - expect(val).to.be(2); - }) - .then(() => cache.resolveFunc(key2)); + const val5 = await cache.resolveFunc(key1); + + expect(val5).to.be(0); + const val4 = await cache.resolveFunc(key1); + expect(val4).to.be(0); + const val3 = await cache.resolveFunc(key2); + expect(val3).to.be(1); + cache.invalidateFunc(key1); + const val2 = await cache.resolveFunc(key1); + expect(val2).to.be(2); + + const val = await cache.resolveFunc(key2); expect(val).to.be(1); }); @@ -100,27 +87,18 @@ describe('cache', () => { const key = cache.registerFunc(1, null, func); this.timeout(3000); - const val = await cache - .resolveFunc(key) - .then((val) => { - expect(val).to.be(0); - }) - .then(() => new Promise((resolve) => setTimeout(resolve, 500))) - .then(() => { - return cache.resolveFunc(key); - }) - .then((val) => { - expect(val).to.be(0); - }) - .then(() => new Promise((resolve) => setTimeout(resolve, 1000))) - .then(() => { - return cache.resolveFunc(key); - }) - .then((val) => { - expect(val).to.be(1); - }) - .then(() => new Promise((resolve) => setTimeout(resolve, 500))) - .then(() => cache.resolveFunc(key)); + const val4 = await cache.resolveFunc(key); + + expect(val4).to.be(0); + await new Promise((resolve) => setTimeout(resolve, 500)); + const val3 = await cache.resolveFunc(key); + expect(val3).to.be(0); + await new Promise((resolve) => setTimeout(resolve, 1000)); + const val2 = await cache.resolveFunc(key); + expect(val2).to.be(1); + await new Promise((resolve) => setTimeout(resolve, 500)); + + const val = await cache.resolveFunc(key); expect(val).to.be(1); }); diff --git a/test/spec.git-api.branching.js b/test/spec.git-api.branching.js index 38997bdc1..b96b42d9c 100644 --- a/test/spec.git-api.branching.js +++ b/test/spec.git-api.branching.js @@ -19,12 +19,10 @@ describe('git-api branching', function () { this.timeout(8000); before(async () => { - const res = await common - .initRepo(req) - .then((res) => { - testDir = res; - }) - .then(() => common.get(req, '/gitconfig', { path: testDir })); + const res2 = await common.initRepo(req); + + testDir = res2; + const res = await common.get(req, '/gitconfig', { path: testDir }); gitConfig = res; }); diff --git a/test/spec.git-api.conflict-no-auto-stash.js b/test/spec.git-api.conflict-no-auto-stash.js index f78e86f9b..2ef2ae568 100644 --- a/test/spec.git-api.conflict-no-auto-stash.js +++ b/test/spec.git-api.conflict-no-auto-stash.js @@ -22,15 +22,16 @@ describe('git-api conflict checkout no auto stash', function () { const dir = await common.initRepo(req); testDir = dir; - await common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'a', files: [{ name: testFile1 }] }) - ) - .then(() => - common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) - ) - .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })); + await common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }); + + await common.post(req, '/commit', { + path: testDir, + message: 'a', + files: [{ name: testFile1 }], + }); + await common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }); + + await common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }); return common.post(req, '/commit', { path: testDir, diff --git a/test/spec.git-api.conflict.js b/test/spec.git-api.conflict.js index 57eda0c10..a9caac403 100644 --- a/test/spec.git-api.conflict.js +++ b/test/spec.git-api.conflict.js @@ -25,28 +25,26 @@ describe('git-api conflict rebase', function () { const dir = await common.initRepo(req); testDir = dir; - await common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ) - .then(() => - common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) - ) - .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ) - .then(() => common.post(req, '/checkout', { path: testDir, name: testBranch })) - .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })); + await common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }); + + await common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], + }); + + await common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }); + await common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }); + + await common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], + }); + + await common.post(req, '/checkout', { path: testDir, name: testBranch }); + + await common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }); return common.post(req, '/commit', { path: testDir, @@ -110,15 +108,16 @@ describe('git-api conflict checkout', function () { const dir = await common.initRepo(req); testDir = dir; - await common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'a', files: [{ name: testFile1 }] }) - ) - .then(() => - common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) - ) - .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })); + await common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }); + + await common.post(req, '/commit', { + path: testDir, + message: 'a', + files: [{ name: testFile1 }], + }); + await common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }); + + await common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }); return common.post(req, '/commit', { path: testDir, @@ -174,20 +173,23 @@ describe('git-api conflict merge', function () { const dir = await common.initRepo(req); testDir = dir; - await common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'a', files: [{ name: testFile1 }] }) - ) - .then(() => - common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) - ) - .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })) - .then(() => - common.post(req, '/commit', { path: testDir, message: 'b', files: [{ name: testFile1 }] }) - ) - .then(() => common.post(req, '/checkout', { path: testDir, name: testBranch })) - .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })); + await common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }); + + await common.post(req, '/commit', { + path: testDir, + message: 'a', + files: [{ name: testFile1 }], + }); + await common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }); + await common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }); + await common.post(req, '/commit', { + path: testDir, + message: 'b', + files: [{ name: testFile1 }], + }); + await common.post(req, '/checkout', { path: testDir, name: testBranch }); + + await common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }); return common.post(req, '/commit', { path: testDir, @@ -270,28 +272,26 @@ describe('git-api conflict solve by deleting', function () { const dir = await common.initRepo(req); testDir = dir; - await common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ) - .then(() => - common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }) - ) - .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: commitMessage, - files: [{ name: testFile1 }], - }) - ) - .then(() => common.post(req, '/checkout', { path: testDir, name: testBranch })) - .then(() => common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) })); + await common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }); + + await common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], + }); + + await common.post(req, '/branches', { path: testDir, name: testBranch, startPoint: 'master' }); + await common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }); + + await common.post(req, '/commit', { + path: testDir, + message: commitMessage, + files: [{ name: testFile1 }], + }); + + await common.post(req, '/checkout', { path: testDir, name: testBranch }); + + await common.post(req, '/testing/changefile', { file: path.join(testDir, testFile1) }); return common.post(req, '/commit', { path: testDir, diff --git a/test/spec.git-api.diff.js b/test/spec.git-api.diff.js index 8df5781d4..7ea1863df 100644 --- a/test/spec.git-api.diff.js +++ b/test/spec.git-api.diff.js @@ -16,10 +16,10 @@ describe('git-api diff', () => { let testDir, testBareDir; before(async () => { - const dir = await common - .initRepo(req) - .then((dir) => (testDir = dir)) - .then(() => common.initRepo(req, { bare: true })); + const dir2 = await common.initRepo(req); + + testDir = dir2; + const dir = await common.initRepo(req, { bare: true }); return (testBareDir = dir); }); @@ -81,9 +81,12 @@ describe('git-api diff', () => { }); it('diff on first commit should work', async () => { - const res = await common.get(req, '/gitlog', { path: testDir }).then((res) => { - expect(res.nodes.length).to.be(2); - return common.get(req, '/diff', { path: testDir, file: testFile, sha1: res.nodes[1].sha1 }); + const res2 = await common.get(req, '/gitlog', { path: testDir }); + expect(res2.nodes.length).to.be(2); + const res = await common.get(req, '/diff', { + path: testDir, + file: testFile, + sha1: res2.nodes[1].sha1, }); for (let i = 0; i < content.length; i++) { @@ -126,9 +129,12 @@ describe('git-api diff', () => { }); it('diff on file commit should work if file is changing', async () => { - const res = await common.get(req, '/gitlog', { path: testDir }).then((res) => { - expect(res.nodes.length).to.be(2); - return common.get(req, '/diff', { path: testDir, file: testFile, sha1: res.nodes[1].sha1 }); + const res2 = await common.get(req, '/gitlog', { path: testDir }); + expect(res2.nodes.length).to.be(2); + const res = await common.get(req, '/diff', { + path: testDir, + file: testFile, + sha1: res2.nodes[1].sha1, }); expect(res.indexOf('diff --git a/afile.txt b/afile.txt')).to.be.above(-1); @@ -182,14 +188,13 @@ describe('git-api diff', () => { }); it('diff on commit with renamed and modified file should work', async () => { - const res = await common.get(req, '/gitlog', { path: testDir }).then((res) => { - expect(res.nodes.length).to.be(3); - return common.get(req, '/diff', { - path: testDir, - file: testFile2, - oldFile: testFile, - sha1: res.nodes[0].sha1, - }); + const res2 = await common.get(req, '/gitlog', { path: testDir }); + expect(res2.nodes.length).to.be(3); + const res = await common.get(req, '/diff', { + path: testDir, + file: testFile2, + oldFile: testFile, + sha1: res2.nodes[0].sha1, }); for (let i = 0; i < content.length; i++) { @@ -229,11 +234,11 @@ describe('git-api diff', () => { }); it('diff on bare repository file should work', async () => { + await common.post(req, '/remotes/barerepository', { path: testDir, url: testBareDir }); + + await common.post(req, '/push', { path: testDir, remote: 'barerepository' }); // first add remote and push all commits - const res = await common - .post(req, '/remotes/barerepository', { path: testDir, url: testBareDir }) - .then(() => common.post(req, '/push', { path: testDir, remote: 'barerepository' })) - .then(() => common.get(req, '/gitlog', { path: testDir })); + const res = await common.get(req, '/gitlog', { path: testDir }); // find a commit which contains the testFile const commit = res.nodes.filter((commit) => diff --git a/test/spec.git-api.discardchanges.js b/test/spec.git-api.discardchanges.js index bbd09e52f..521ceade8 100644 --- a/test/spec.git-api.discardchanges.js +++ b/test/spec.git-api.discardchanges.js @@ -19,10 +19,11 @@ describe('git-api discardchanges', () => { const dir = await common.createSmallRepo(req); const testFile1 = 'test.txt'; - const res = await common - .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) - .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) - .then(() => common.get(req, '/status', { path: dir })); + await common.post(req, '/testing/createfile', { file: path.join(dir, testFile1) }); + + await common.post(req, '/discardchanges', { path: dir, file: testFile1 }); + + const res = await common.get(req, '/status', { path: dir }); return expect(Object.keys(res.files).length).to.be(0); }); @@ -31,14 +32,13 @@ describe('git-api discardchanges', () => { const dir = await common.createSmallRepo(req); const testFile1 = 'test.txt'; - const res = await common - .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) - .then(() => - common.post(req, '/commit', { path: dir, message: 'lol', files: [{ name: testFile1 }] }) - ) - .then(() => common.post(req, '/testing/changefile', { file: path.join(dir, testFile1) })) - .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) - .then(() => common.get(req, '/status', { path: dir })); + await common.post(req, '/testing/createfile', { file: path.join(dir, testFile1) }); + + await common.post(req, '/commit', { path: dir, message: 'lol', files: [{ name: testFile1 }] }); + await common.post(req, '/testing/changefile', { file: path.join(dir, testFile1) }); + await common.post(req, '/discardchanges', { path: dir, file: testFile1 }); + + const res = await common.get(req, '/status', { path: dir }); return expect(Object.keys(res.files).length).to.be(0); }); @@ -47,14 +47,13 @@ describe('git-api discardchanges', () => { const dir = await common.createSmallRepo(req); const testFile1 = 'test.txt'; - const res = await common - .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) - .then(() => - common.post(req, '/commit', { path: dir, message: 'lol', files: [{ name: testFile1 }] }) - ) - .then(() => common.post(req, '/testing/removefile', { file: path.join(dir, testFile1) })) - .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) - .then(() => common.get(req, '/status', { path: dir })); + await common.post(req, '/testing/createfile', { file: path.join(dir, testFile1) }); + + await common.post(req, '/commit', { path: dir, message: 'lol', files: [{ name: testFile1 }] }); + await common.post(req, '/testing/removefile', { file: path.join(dir, testFile1) }); + await common.post(req, '/discardchanges', { path: dir, file: testFile1 }); + + const res = await common.get(req, '/status', { path: dir }); return expect(Object.keys(res.files).length).to.be(0); }); @@ -63,11 +62,12 @@ describe('git-api discardchanges', () => { const dir = await common.createSmallRepo(req); const testFile1 = 'test.txt'; - const res = await common - .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) - .then(() => common.post(req, '/testing/git', { path: dir, command: ['add', testFile1] })) - .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) - .then(() => common.get(req, '/status', { path: dir })); + await common.post(req, '/testing/createfile', { file: path.join(dir, testFile1) }); + + await common.post(req, '/testing/git', { path: dir, command: ['add', testFile1] }); + await common.post(req, '/discardchanges', { path: dir, file: testFile1 }); + + const res = await common.get(req, '/status', { path: dir }); return expect(Object.keys(res.files).length).to.be(0); }); @@ -76,12 +76,13 @@ describe('git-api discardchanges', () => { const dir = await common.createSmallRepo(req); const testFile1 = 'test.txt'; - const res = await common - .post(req, '/testing/createfile', { file: path.join(dir, testFile1) }) - .then(() => common.post(req, '/testing/git', { path: dir, command: ['add', testFile1] })) - .then(() => common.post(req, '/testing/removefile', { file: path.join(dir, testFile1) })) - .then(() => common.post(req, '/discardchanges', { path: dir, file: testFile1 })) - .then(() => common.get(req, '/status', { path: dir })); + await common.post(req, '/testing/createfile', { file: path.join(dir, testFile1) }); + + await common.post(req, '/testing/git', { path: dir, command: ['add', testFile1] }); + await common.post(req, '/testing/removefile', { file: path.join(dir, testFile1) }); + await common.post(req, '/discardchanges', { path: dir, file: testFile1 }); + + const res = await common.get(req, '/status', { path: dir }); return expect(Object.keys(res.files).length).to.be(0); }); @@ -91,27 +92,30 @@ describe('git-api discardchanges', () => { const submodulePath = 'subrepo'; this.timeout(5000); - const dir = await common.createSmallRepo(req).then(async (dir) => { - const subrepoDir = await common.createSmallRepo(req); + const dir2 = await common.createSmallRepo(req); + const subrepoDir = await common.createSmallRepo(req); + + await common.post(req, '/submodules/add', { + submoduleUrl: subrepoDir, + submodulePath: submodulePath, + path: dir2, + }); - await common.post(req, '/submodules/add', { - submoduleUrl: subrepoDir, - submodulePath: submodulePath, - path: dir, - }); + const dir = await dir2; - return dir; + await common.post(req, '/commit', { + path: dir, + message: 'lol', + files: [{ name: '.gitmodules' }], }); - const res = await common - .post(req, '/commit', { path: dir, message: 'lol', files: [{ name: '.gitmodules' }] }) - .then(() => - common.post(req, '/testing/changefile', { - file: path.join(dir, submodulePath, testFile), - }) - ) - .then(() => common.post(req, '/discardchanges', { path: dir, file: submodulePath })) - .then(() => common.get(req, '/status', { path: dir })); + await common.post(req, '/testing/changefile', { + file: path.join(dir, submodulePath, testFile), + }); + + await common.post(req, '/discardchanges', { path: dir, file: submodulePath }); + + const res = await common.get(req, '/status', { path: dir }); return expect(Object.keys(res.files).length).to.be(0); }); diff --git a/test/spec.git-api.ignorefile.js b/test/spec.git-api.ignorefile.js index 6f90f3c7d..34ee8c47c 100644 --- a/test/spec.git-api.ignorefile.js +++ b/test/spec.git-api.ignorefile.js @@ -20,15 +20,15 @@ describe('git-api: test ignorefile call', () => { const dir = await common.createSmallRepo(req); const testFile = 'test.txt'; + await fs.writeFile(path.join(dir, '.gitignore'), 'test git ignore file...'); + + await common.post(req, '/testing/createfile', { file: path.join(dir, testFile) }); + // Create .gitignore file prior to append - await fs - .writeFile(path.join(dir, '.gitignore'), 'test git ignore file...') - .then(() => common.post(req, '/testing/createfile', { file: path.join(dir, testFile) })) - .then(() => common.post(req, '/ignorefile', { path: dir, file: testFile })) - .then(async () => { - const res = await common.get(req, '/status', { path: dir }); - expect(Object.keys(res.files).toString()).to.be('.gitignore'); - }); + await common.post(req, '/ignorefile', { path: dir, file: testFile }); + + const res = await common.get(req, '/status', { path: dir }); + expect(Object.keys(res.files).toString()).to.be('.gitignore'); const data = await fs.readFile(path.join(dir, '.gitignore')); if (data.toString().indexOf(testFile) < 0) { @@ -40,13 +40,11 @@ describe('git-api: test ignorefile call', () => { const dir = await common.createSmallRepo(req); const testFile = 'test.txt'; - await common - .post(req, '/testing/createfile', { file: path.join(dir, testFile) }) - .then(() => common.post(req, '/ignorefile', { path: dir, file: testFile })) - .then(async () => { - const res = await common.get(req, '/status', { path: dir }); - expect(Object.keys(res.files).toString()).to.be('.gitignore'); - }); + await common.post(req, '/testing/createfile', { file: path.join(dir, testFile) }); + + await common.post(req, '/ignorefile', { path: dir, file: testFile }); + const res = await common.get(req, '/status', { path: dir }); + expect(Object.keys(res.files).toString()).to.be('.gitignore'); const data = await fs.readFile(path.join(dir, '.gitignore')); if (data.toString().indexOf(testFile) < 0) { @@ -58,15 +56,15 @@ describe('git-api: test ignorefile call', () => { const dir = await common.createSmallRepo(req); const testFile = 'test.txt'; + await fs.appendFile(path.join(dir, '.gitignore'), testFile.split('.')[0]); + + await common.post(req, '/testing/createfile', { file: path.join(dir, testFile) }); + // add part of file name to gitignore - await fs - .appendFile(path.join(dir, '.gitignore'), testFile.split('.')[0]) - .then(() => common.post(req, '/testing/createfile', { file: path.join(dir, testFile) })) - .then(() => common.post(req, '/ignorefile', { path: dir, file: testFile })) - .then(async () => { - const res = await common.get(req, '/status', { path: dir }); - expect(Object.keys(res.files).toString()).to.be('.gitignore'); - }); + await common.post(req, '/ignorefile', { path: dir, file: testFile }); + + const res = await common.get(req, '/status', { path: dir }); + expect(Object.keys(res.files).toString()).to.be('.gitignore'); const data = await fs.readFile(path.join(dir, '.gitignore')); if (data.toString().indexOf(testFile) < 0) { diff --git a/test/spec.git-api.js b/test/spec.git-api.js index 7f144cb2c..0d83e8e33 100644 --- a/test/spec.git-api.js +++ b/test/spec.git-api.js @@ -398,12 +398,12 @@ describe('git-api', () => { }); it('test gitignore api endpoint', async () => { - const res = await common - .put(req, '/gitignore', { path: testDir, data: 'abc' }) - .then(() => common.get(req, '/gitignore', { path: testDir })) - .then((res) => expect(res.content).to.be('abc')) - .then(() => common.put(req, '/gitignore', { path: testDir, data: '' })) - .then(() => common.get(req, '/gitignore', { path: testDir })); + await common.put(req, '/gitignore', { path: testDir, data: 'abc' }); + + const res2 = await common.get(req, '/gitignore', { path: testDir }); + await expect(res2.content).to.be('abc'); + await common.put(req, '/gitignore', { path: testDir, data: '' }); + const res = await common.get(req, '/gitignore', { path: testDir }); return expect(res.content).to.be(''); }); diff --git a/test/spec.git-api.patch.js b/test/spec.git-api.patch.js index 99ebb7761..55457cf21 100644 --- a/test/spec.git-api.patch.js +++ b/test/spec.git-api.patch.js @@ -15,25 +15,22 @@ let testDir; const req = request(app); const testPatch = async (req, testDir, testFileName, contentsToPatch, files) => { + await common.post(req, '/testing/createfile', { + file: path.join(testDir, testFileName), + content: contentsToPatch[0], + }); + + await common.post(req, '/commit', { + path: testDir, + message: `a commit for ${testFileName}`, + files: [{ name: testFileName }], + }); + // testDir = '/tmp/testdir'; - await common - .post(req, '/testing/createfile', { - file: path.join(testDir, testFileName), - content: contentsToPatch[0], - }) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: `a commit for ${testFileName}`, - files: [{ name: testFileName }], - }) - ) - .then(() => - common.post(req, '/testing/changefile', { - file: path.join(testDir, testFileName), - content: contentsToPatch[1], - }) - ); + await common.post(req, '/testing/changefile', { + file: path.join(testDir, testFileName), + content: contentsToPatch[1], + }); return common.post(req, '/commit', { path: testDir, diff --git a/test/spec.git-api.remote.js b/test/spec.git-api.remote.js index 29404845f..ad30f9883 100644 --- a/test/spec.git-api.remote.js +++ b/test/spec.git-api.remote.js @@ -19,16 +19,12 @@ describe('git-api remote', function () { this.timeout(4000); before('creating test dirs should work', async () => { - const dir = await common - .post(req, '/testing/createtempdir') - .then((dir) => { - testDirLocal1 = dir.path; - }) - .then(() => common.post(req, '/testing/createtempdir')) - .then((dir) => { - testDirLocal2 = dir.path; - }) - .then(() => common.post(req, '/testing/createtempdir')); + const dir3 = await common.post(req, '/testing/createtempdir'); + + testDirLocal1 = dir3.path; + const dir2 = await common.post(req, '/testing/createtempdir'); + testDirLocal2 = dir2.path; + const dir = await common.post(req, '/testing/createtempdir'); testDirRemote = dir.path; }); @@ -114,16 +110,15 @@ describe('git-api remote', function () { it('creating and pushing a commit in "local1" repo should work', async () => { const testFile = path.join(testDirLocal1, 'testfile2.txt'); - await common - .post(req, '/testing/createfile', { file: testFile }) - .then(() => new Promise((resolve) => setTimeout(resolve, 500))) - .then(() => - common.post(req, '/commit', { - path: testDirLocal1, - message: 'Commit2', - files: [{ name: testFile }], - }) - ); + await common.post(req, '/testing/createfile', { file: testFile }); + + await new Promise((resolve) => setTimeout(resolve, 500)); + + await common.post(req, '/commit', { + path: testDirLocal1, + message: 'Commit2', + files: [{ name: testFile }], + }); return common.post(req, '/push', { path: testDirLocal1, remote: 'origin' }); }); @@ -170,9 +165,9 @@ describe('git-api remote', function () { it('creating a commit in "local2" repo should work', async () => { const testFile = path.join(testDirLocal2, 'testfile3.txt'); - await common - .post(req, '/testing/createfile', { file: testFile }) - .then(() => new Promise((resolve) => setTimeout(resolve, 500))); + await common.post(req, '/testing/createfile', { file: testFile }); + + await new Promise((resolve) => setTimeout(resolve, 500)); return common.post(req, '/commit', { path: testDirLocal2, diff --git a/test/spec.git-api.squash.js b/test/spec.git-api.squash.js index 57c8058eb..e83c1ec38 100644 --- a/test/spec.git-api.squash.js +++ b/test/spec.git-api.squash.js @@ -35,16 +35,15 @@ describe('git-api conflict rebase', function () { }); it('create some commits', async () => { - await common - .post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }) - .then(() => - common.post(req, '/commit', { - path: testDir, - message: `a commit for ${testFile1}`, - files: [{ name: testFile1 }], - }) - ) - .then(() => common.post(req, '/testing/createfile', { file: path.join(testDir, testFile2) })); + await common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }); + + await common.post(req, '/commit', { + path: testDir, + message: `a commit for ${testFile1}`, + files: [{ name: testFile1 }], + }); + + await common.post(req, '/testing/createfile', { file: path.join(testDir, testFile2) }); return common.post(req, '/commit', { path: testDir, @@ -58,17 +57,17 @@ describe('git-api conflict rebase', function () { }); it('squash 2 commits to 1', async () => { - const res = await common - .post(req, '/squash', { path: testDir, target: 'master' }) - .then(() => common.get(req, '/status', { path: testDir })); + await common.post(req, '/squash', { path: testDir, target: 'master' }); + + const res = await common.get(req, '/status', { path: testDir }); return expect(Object.keys(res.files).length).to.be(2); }); it('discard all', async () => { - const res = await common - .post(req, '/discardchanges', { path: testDir, all: true }) - .then(() => common.get(req, '/status', { path: testDir })); + await common.post(req, '/discardchanges', { path: testDir, all: true }); + + const res = await common.get(req, '/status', { path: testDir }); return expect(Object.keys(res.files).length).to.be(0); }); @@ -84,9 +83,9 @@ describe('git-api conflict rebase', function () { }); it('squash 2 commits to 1 with conflict', async () => { - const res = await common - .post(req, '/squash', { path: testDir, target: 'master' }) - .then(() => common.get(req, '/status', { path: testDir })); + await common.post(req, '/squash', { path: testDir, target: 'master' }); + + const res = await common.get(req, '/status', { path: testDir }); expect(res.inConflict).to.be(true); expect(Object.keys(res.files).length).to.be(2); diff --git a/test/spec.git-api.stash.js b/test/spec.git-api.stash.js index 7bf1df823..61511a424 100644 --- a/test/spec.git-api.stash.js +++ b/test/spec.git-api.stash.js @@ -20,9 +20,8 @@ describe('git-api conflict rebase', function () { const testFile1 = 'testfile1.txt'; before(async () => { - await common.createSmallRepo(req).then((dir) => { - testDir = dir; - }); + const dir = await common.createSmallRepo(req); + testDir = dir; return common.post(req, '/testing/createfile', { file: path.join(testDir, testFile1) }); }); diff --git a/test/spec.git-api.submodule.js b/test/spec.git-api.submodule.js index 08dcd434a..bc282d4de 100644 --- a/test/spec.git-api.submodule.js +++ b/test/spec.git-api.submodule.js @@ -18,12 +18,10 @@ describe('git-api submodule', function () { let testDirMain, testDirSecondary; before(async () => { - const dir = await common - .createSmallRepo(req) - .then((dir) => { - testDirMain = dir; - }) - .then(() => common.createSmallRepo(req)); + const dir2 = await common.createSmallRepo(req); + + testDirMain = dir2; + const dir = await common.createSmallRepo(req); testDirSecondary = dir; }); From 4601915726f79c9bf3be8b461ef6fa175ac3388b Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Mon, 11 May 2020 16:55:03 +0200 Subject: [PATCH 3/7] fixup ungit-plugin --- source/ungit-plugin.js | 92 +++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 59 deletions(-) diff --git a/source/ungit-plugin.js b/source/ungit-plugin.js index c5338ba8f..f17a40183 100644 --- a/source/ungit-plugin.js +++ b/source/ungit-plugin.js @@ -43,66 +43,40 @@ class UngitPlugin { winston.info(`Compiling plugin ${this.path}`); const exports = this.manifest.exports || {}; - const result = await Promise.resolve() - .then(() => { - if (exports.raw) { - return Promise.all( - assureArray(exports.raw).map(async (rawSource) => { - const text = await fs.readFile(path.join(this.path, rawSource)); - return text + '\n'; - }) - ).then((result) => { - return result.join('\n'); - }); - } else { - return ''; - } - }) - .then((result) => { - if (exports.javascript) { - return ( - result + - assureArray(exports.javascript) - .map((filename) => { - return ``; - }) - .join('\n') - ); - } else { - return result; - } - }) - .then((result) => { - if (exports.knockoutTemplates) { - return Promise.all( - Object.keys(exports.knockoutTemplates).map(async (templateName) => { - const text = await fs.readFile( - path.join(this.path, exports.knockoutTemplates[templateName]) - ); + let result = ''; + if (exports.raw) + result += ( + await Promise.all( + assureArray(exports.raw).map(async (rawSource) => { + const text = await fs.readFile(path.join(this.path, rawSource)); + return text + '\n'; + }) + ) + ).join('\n'); + if (exports.javascript) + result += assureArray(exports.javascript) + .map((filename) => { + return ``; + }) + .join('\n'); + if (exports.knockoutTemplates) + result += ( + await Promise.all( + Object.keys(exports.knockoutTemplates).map(async (templateName) => { + const text = await fs.readFile( + path.join(this.path, exports.knockoutTemplates[templateName]) + ); - return ``; - }) - ).then((templates) => { - return result + templates.join('\n'); - }); - } else { - return result; - } - }) - .then((result2) => { - if (exports.css) { - return ( - result2 + - assureArray(exports.css) - .map((cssSource) => { - return ``; - }) - .join('\n') - ); - } else { - return result2; - } - }); + return ``; + }) + ) + ).join('\n'); + if (exports.css) + result += assureArray(exports.css) + .map((cssSource) => { + return ``; + }) + .join('\n'); return `\n${result}`; } From f435931e0ea4fa68bb23ce55872fa977a33eb2b7 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Tue, 12 May 2020 00:01:47 +0200 Subject: [PATCH 4/7] fixup git-ref remove --- components/graph/git-ref.js | 41 +++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/components/graph/git-ref.js b/components/graph/git-ref.js index 0fa75a29d..398c9faba 100644 --- a/components/graph/git-ref.js +++ b/components/graph/git-ref.js @@ -174,33 +174,31 @@ class RefViewModel extends Selectable { } } - remove(isClientOnly) { + async remove(isClientOnly) { let url = this.isTag ? '/tags' : '/branches'; if (this.isRemote) url = `/remote${url}`; - - return (isClientOnly - ? Promise.resolve() - : this.server.delPromise(url, { + try { + if (!isClientOnly) + await this.server.delPromise(url, { path: this.graph.repoPath(), remote: this.isRemote ? this.remote : null, name: this.refName, - }) - ) - .then(() => { - if (this.node()) this.node().removeRef(this); - this.graph.refs.remove(this); - delete this.graph.refsByRefName[this.name]; - }) - .catch((e) => this.server.unhandledRejection(e)) - .finally(() => { - if (!isClientOnly) { - if (url == '/remote/tags') { - programEvents.dispatch({ event: 'request-fetch-tags' }); - } else { - programEvents.dispatch({ event: 'branch-updated' }); - } + }); + + if (this.node()) this.node().removeRef(this); + this.graph.refs.remove(this); + delete this.graph.refsByRefName[this.name]; + } catch (e) { + this.server.unhandledRejection(e); + } finally { + if (!isClientOnly) { + if (url == '/remote/tags') { + programEvents.dispatch({ event: 'request-fetch-tags' }); + } else { + programEvents.dispatch({ event: 'branch-updated' }); } - }); + } + } } getLocalRef() { @@ -247,7 +245,6 @@ class RefViewModel extends Selectable { const isLocalCurrent = this.getLocalRef() && this.getLocalRef().current(); try { - await Promise.resolve(); if (isRemote && !isLocalCurrent) { return this.server.postPromise('/branches', { path: this.graph.repoPath(), From 038f465999281888ab26118ddc8b8a108c73f268 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Tue, 12 May 2020 00:04:08 +0200 Subject: [PATCH 5/7] fixup textdiff --- components/textdiff/textdiff.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/textdiff/textdiff.js b/components/textdiff/textdiff.js index 29e743e6d..9789b7aaa 100644 --- a/components/textdiff/textdiff.js +++ b/components/textdiff/textdiff.js @@ -131,7 +131,7 @@ class TextDiffViewModel { } async render() { - (await !this.diffJson) ? this.getDiffJson() : Promise.resolve(); + if (!this.diffJson) await this.getDiffJson(); if (!this.diffJson || this.diffJson.length == 0) return; // check if diffs are available (binary files do not support them) if (!this.diffJson[0].allBlocks) { From a63e221de98a7cdfef12081551fbde2ac43f69db Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Tue, 12 May 2020 00:06:15 +0200 Subject: [PATCH 6/7] fixup registerApi --- source/git-api.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/source/git-api.js b/source/git-api.js index feaee94c4..c21a14f2e 100644 --- a/source/git-api.js +++ b/source/git-api.js @@ -441,19 +441,21 @@ exports.registerApi = (env) => { if (res.setTimeout) res.setTimeout(tenMinTimeoutMs); const task = gitPromise(['remote'], req.query.path) - .then((remoteText) => { + .then(async (remoteText) => { const remotes = remoteText.trim().split('\n'); // making calls serially as credential helpers may get confused to which cred to get. - return remotes.reduce(async (promise, remote) => { - if (!remote || remote === '') return promise; - await promise; - return gitPromise({ + for (const remote of remotes) { + if (!remote) continue; + await gitPromise({ commands: credentialsOption(req.query.socketId, remote).concat(['fetch', remote]), repoPath: req.query.path, timeout: tenMinTimeoutMs, - }).catch((e) => winston.warn('err during remote fetch for /refs', e)); // ignore fetch err as it is most likely credential - }, Promise.resolve()); + }).catch((e) => + // ignore fetch err as it is most likely credential + winston.warn('err during remote fetch for /refs', e) + ); + } }) .then(() => gitPromise(['show-ref', '-d'], req.query.path)) // On new fresh repos, empty string is returned but has status code of error, simply ignoring them From 2a92a23446ddf7e6b16e42baa051adeb925ff245 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Tue, 12 May 2020 00:26:48 +0200 Subject: [PATCH 7/7] jshint: allow async/await --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index b4f3a46dd..3041fc2ee 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -67,7 +67,7 @@ module.exports = (grunt) => { options: { undef: true, // check for usage of undefined constiables indent: 2, - esversion: 6, + esversion: 8, laxbreak: true, '-W033': true, // ignore Missing semicolon '-W041': true, // ignore Use '===' to compare with '0'