diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index b910537bffe7b484380692037dbdaae4b93d9216..19c3cbdbe59c87be5a7850d12b86d584e0a64236 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -252,7 +252,7 @@ export class CommandCenter { gitRef = indexStatus ? '' : 'HEAD'; } - const { size, object } = await repository.lstree(gitRef, uri.fsPath); + const { size, object } = await repository.getObjectDetails(gitRef, uri.fsPath); const { mimetype } = await repository.detectObjectType(object); if (mimetype === 'text/plain') { diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 6cd7e5afa4661ec191e085758a12607d3411a22e..cea9edd799abf27366c71c250e5f5b0ac975d374 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -647,15 +647,16 @@ interface LsTreeElement { mode: string; type: string; object: string; + size: string; file: string; } export function parseLsTree(raw: string): LsTreeElement[] { return raw.split('\n') .filter(l => !!l) - .map(line => /^(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/.exec(line)!) + .map(line => /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/.exec(line)!) .filter(m => !!m) - .map(([, mode, type, object, file]) => ({ mode, type, object, file })); + .map(([, mode, type, object, size, file]) => ({ mode, type, object, size, file })); } interface LsFilesElement { @@ -759,37 +760,33 @@ export class Repository { return stdout; } - async lstree(treeish: string, path: string): Promise<{ mode: string, object: string, size: number }> { + async getObjectDetails(treeish: string, path: string): Promise<{ mode: string, object: string, size: number }> { if (!treeish) { // index - const { stdout } = await this.run(['ls-files', '--stage', '--', path]); - - const match = /^(\d+)\s+([0-9a-f]{40})\s+(\d+)/.exec(stdout); + const elements = await this.lsfiles(path); - if (!match) { + if (elements.length === 0) { throw new GitError({ message: 'Error running ls-files' }); } - const [, mode, object] = match; + const { mode, object } = elements[0]; const catFile = await this.run(['cat-file', '-s', object]); const size = parseInt(catFile.stdout); return { mode, object, size }; } - const { stdout } = await this.run(['ls-tree', '-l', treeish, '--', path]); - - const match = /^(\d+)\s+(\w+)\s+([0-9a-f]{40})\s+(\d+)/.exec(stdout); + const elements = await this.lstree(treeish, path); - if (!match) { - throw new GitError({ message: 'Error running ls-tree' }); + if (elements.length === 0) { + throw new GitError({ message: 'Error running ls-files' }); } - const [, mode, , object, size] = match; + const { mode, object, size } = elements[0]; return { mode, object, size: parseInt(size) }; } - async lstree2(treeish: string, path: string): Promise { - const { stdout } = await this.run(['ls-tree', treeish, '--', path]); + async lstree(treeish: string, path: string): Promise { + const { stdout } = await this.run(['ls-tree', '-l', treeish, '--', path]); return parseLsTree(stdout); } @@ -801,7 +798,7 @@ export class Repository { async getGitRelativePath(treeish: string, relativePath: string): Promise { const relativePathLowercase = relativePath.toLowerCase(); const dirname = path.posix.dirname(relativePath) + '/'; - const elements: { file: string; }[] = treeish ? await this.lstree2(treeish, dirname) : await this.lsfiles(dirname); + const elements: { file: string; }[] = treeish ? await this.lstree(treeish, dirname) : await this.lsfiles(dirname); const element = elements.filter(file => file.file.toLowerCase() === relativePathLowercase)[0]; if (!element) { @@ -893,7 +890,7 @@ export class Repository { let mode: string; try { - const details = await this.lstree('HEAD', path); + const details = await this.getObjectDetails('HEAD', path); mode = details.mode; } catch (err) { mode = '100644'; diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 7c55a0ce22f6a6a406b29200f5504e79283faeca..ece6ef8fb37f50bd1777eacfc12e8bb888fbf40c 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -299,7 +299,7 @@ export enum Operation { Tag = 'Tag', Stash = 'Stash', CheckIgnore = 'CheckIgnore', - LSTree = 'LSTree', + GetObjectDetails = 'GetObjectDetails', SubmoduleUpdate = 'SubmoduleUpdate', RebaseContinue = 'RebaseContinue', } @@ -309,7 +309,7 @@ function isReadOnly(operation: Operation): boolean { case Operation.Show: case Operation.GetCommitTemplate: case Operation.CheckIgnore: - case Operation.LSTree: + case Operation.GetObjectDetails: return true; default: return false; @@ -320,7 +320,7 @@ function shouldShowProgress(operation: Operation): boolean { switch (operation) { case Operation.Fetch: case Operation.CheckIgnore: - case Operation.LSTree: + case Operation.GetObjectDetails: case Operation.Show: return false; default: @@ -906,8 +906,8 @@ export class Repository implements Disposable { }); } - lstree(ref: string, filePath: string): Promise<{ mode: string, object: string, size: number }> { - return this.run(Operation.LSTree, () => this.repository.lstree(ref, filePath)); + getObjectDetails(ref: string, filePath: string): Promise<{ mode: string, object: string, size: number }> { + return this.run(Operation.GetObjectDetails, () => this.repository.getObjectDetails(ref, filePath)); } detectObjectType(object: string): Promise<{ mimetype: string, encoding?: string }> { diff --git a/extensions/git/src/test/git.test.ts b/extensions/git/src/test/git.test.ts index 76533949e34b6d90cd5ed46e0e9d7939eb13ac6a..eee43347351bf6993bcff2afa3c28b66e525257c 100644 --- a/extensions/git/src/test/git.test.ts +++ b/extensions/git/src/test/git.test.ts @@ -216,32 +216,32 @@ This is a commit message.`; suite('parseLsTree', function () { test('sample', function () { - const input = `040000 tree 0274a81f8ee9ca3669295dc40f510bd2021d0043 .vscode -100644 blob 1d487c1817262e4f20efbfa1d04c18f51b0046f6 Screen Shot 2018-06-01 at 14.48.05.png -100644 blob 686c16e4f019b734655a2576ce8b98749a9ffdb9 Screen Shot 2018-06-07 at 20.04.59.png -100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 boom.txt -100644 blob 86dc360dd25f13fa50ffdc8259e9653921f4f2b7 boomcaboom.txt -100644 blob a68b14060589b16d7ac75f67b905c918c03c06eb file.js -100644 blob f7bcfb05af46850d780f88c069edcd57481d822d file.md -100644 blob ab8b86114a051f6490f1ec5e3141b9a632fb46b5 hello.js -100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 what.js -100644 blob be859e3f412fa86513cd8bebe8189d1ea1a3e46d what.txt -100644 blob 56ec42c9dc6fcf4534788f0fe34b36e09f37d085 what.txt2`; + const input = `040000 tree 0274a81f8ee9ca3669295dc40f510bd2021d0043 - .vscode +100644 blob 1d487c1817262e4f20efbfa1d04c18f51b0046f6 491570 Screen Shot 2018-06-01 at 14.48.05.png +100644 blob 686c16e4f019b734655a2576ce8b98749a9ffdb9 764420 Screen Shot 2018-06-07 at 20.04.59.png +100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 4 boom.txt +100644 blob 86dc360dd25f13fa50ffdc8259e9653921f4f2b7 11 boomcaboom.txt +100644 blob a68b14060589b16d7ac75f67b905c918c03c06eb 24 file.js +100644 blob f7bcfb05af46850d780f88c069edcd57481d822d 201 file.md +100644 blob ab8b86114a051f6490f1ec5e3141b9a632fb46b5 8 hello.js +100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 4 what.js +100644 blob be859e3f412fa86513cd8bebe8189d1ea1a3e46d 24 what.txt +100644 blob 56ec42c9dc6fcf4534788f0fe34b36e09f37d085 261186 what.txt2`; const output = parseLsTree(input); assert.deepEqual(output, [ - { mode: '040000', type: 'tree', object: '0274a81f8ee9ca3669295dc40f510bd2021d0043', file: '.vscode' }, - { mode: '100644', type: 'blob', object: '1d487c1817262e4f20efbfa1d04c18f51b0046f6', file: 'Screen Shot 2018-06-01 at 14.48.05.png' }, - { mode: '100644', type: 'blob', object: '686c16e4f019b734655a2576ce8b98749a9ffdb9', file: 'Screen Shot 2018-06-07 at 20.04.59.png' }, - { mode: '100644', type: 'blob', object: '257cc5642cb1a054f08cc83f2d943e56fd3ebe99', file: 'boom.txt' }, - { mode: '100644', type: 'blob', object: '86dc360dd25f13fa50ffdc8259e9653921f4f2b7', file: 'boomcaboom.txt' }, - { mode: '100644', type: 'blob', object: 'a68b14060589b16d7ac75f67b905c918c03c06eb', file: 'file.js' }, - { mode: '100644', type: 'blob', object: 'f7bcfb05af46850d780f88c069edcd57481d822d', file: 'file.md' }, - { mode: '100644', type: 'blob', object: 'ab8b86114a051f6490f1ec5e3141b9a632fb46b5', file: 'hello.js' }, - { mode: '100644', type: 'blob', object: '257cc5642cb1a054f08cc83f2d943e56fd3ebe99', file: 'what.js' }, - { mode: '100644', type: 'blob', object: 'be859e3f412fa86513cd8bebe8189d1ea1a3e46d', file: 'what.txt' }, - { mode: '100644', type: 'blob', object: '56ec42c9dc6fcf4534788f0fe34b36e09f37d085', file: 'what.txt2' } + { mode: '040000', type: 'tree', object: '0274a81f8ee9ca3669295dc40f510bd2021d0043', size: '-', file: '.vscode' }, + { mode: '100644', type: 'blob', object: '1d487c1817262e4f20efbfa1d04c18f51b0046f6', size: '491570', file: 'Screen Shot 2018-06-01 at 14.48.05.png' }, + { mode: '100644', type: 'blob', object: '686c16e4f019b734655a2576ce8b98749a9ffdb9', size: '764420', file: 'Screen Shot 2018-06-07 at 20.04.59.png' }, + { mode: '100644', type: 'blob', object: '257cc5642cb1a054f08cc83f2d943e56fd3ebe99', size: '4', file: 'boom.txt' }, + { mode: '100644', type: 'blob', object: '86dc360dd25f13fa50ffdc8259e9653921f4f2b7', size: '11', file: 'boomcaboom.txt' }, + { mode: '100644', type: 'blob', object: 'a68b14060589b16d7ac75f67b905c918c03c06eb', size: '24', file: 'file.js' }, + { mode: '100644', type: 'blob', object: 'f7bcfb05af46850d780f88c069edcd57481d822d', size: '201', file: 'file.md' }, + { mode: '100644', type: 'blob', object: 'ab8b86114a051f6490f1ec5e3141b9a632fb46b5', size: '8', file: 'hello.js' }, + { mode: '100644', type: 'blob', object: '257cc5642cb1a054f08cc83f2d943e56fd3ebe99', size: '4', file: 'what.js' }, + { mode: '100644', type: 'blob', object: 'be859e3f412fa86513cd8bebe8189d1ea1a3e46d', size: '24', file: 'what.txt' }, + { mode: '100644', type: 'blob', object: '56ec42c9dc6fcf4534788f0fe34b36e09f37d085', size: '261186', file: 'what.txt2' } ]); }); });