diff --git a/lib/git-shell-out-strategy.js b/lib/git-shell-out-strategy.js index 50c2788298..9e26213b5e 100644 --- a/lib/git-shell-out-strategy.js +++ b/lib/git-shell-out-strategy.js @@ -164,6 +164,7 @@ export default class GitShellOutStrategy { const statusMap = { 'A': 'added', + 'C': 'added', // technically copied, but we'll treat as added 'M': 'modified', 'D': 'deleted', 'U': 'modified', @@ -204,6 +205,10 @@ export default class GitShellOutStrategy { if (x !== ' ' && x !== '?') { stagedFiles[filePath] = statusMap[x]; } + if (x === 'C') { + // skip the next line, which is the copied file + i++; + } } } diff --git a/test/fixtures/repo-copied-file/dot-git/COMMIT_EDITMSG b/test/fixtures/repo-copied-file/dot-git/COMMIT_EDITMSG new file mode 100644 index 0000000000..99c732f855 --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/COMMIT_EDITMSG @@ -0,0 +1 @@ +Add copied file diff --git a/test/fixtures/repo-copied-file/dot-git/HEAD b/test/fixtures/repo-copied-file/dot-git/HEAD new file mode 100644 index 0000000000..cb089cd89a --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/test/fixtures/repo-copied-file/dot-git/audit_log b/test/fixtures/repo-copied-file/dot-git/audit_log new file mode 100644 index 0000000000..fd092070bd --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/audit_log @@ -0,0 +1,3 @@ +refs/heads/master 0000000000000000000000000000000000000000 e25ea76910cdc213d19ca4de30f64f54dded0f3b Michelle Tilley 1485376931 -0800 { "program":"commit", "via":"commit (initial): Add one.cc\n" } +refs/heads/master e25ea76910cdc213d19ca4de30f64f54dded0f3b 5d336c2d72005417e5c84ac691a518a4f053e39b Michelle Tilley 1485376941 -0800 { "program":"commit", "via":"commit (amend): Add one.cc\n" } +refs/heads/master 5d336c2d72005417e5c84ac691a518a4f053e39b 7219822bbcd976b5245f4f37dfdc6243ead0749a Michelle Tilley 1485376979 -0800 { "program":"commit", "via":"commit: Add copied file\n" } diff --git a/test/fixtures/repo-copied-file/dot-git/config b/test/fixtures/repo-copied-file/dot-git/config new file mode 100644 index 0000000000..1f0486d27a --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + ignorecase = true + precomposeunicode = true diff --git a/test/fixtures/repo-copied-file/dot-git/description b/test/fixtures/repo-copied-file/dot-git/description new file mode 100644 index 0000000000..498b267a8c --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/test/fixtures/repo-copied-file/dot-git/index b/test/fixtures/repo-copied-file/dot-git/index new file mode 100644 index 0000000000..e3a7ef8cff Binary files /dev/null and b/test/fixtures/repo-copied-file/dot-git/index differ diff --git a/test/fixtures/repo-copied-file/dot-git/info/exclude b/test/fixtures/repo-copied-file/dot-git/info/exclude new file mode 100644 index 0000000000..a5196d1be8 --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/test/fixtures/repo-copied-file/dot-git/info/refs b/test/fixtures/repo-copied-file/dot-git/info/refs new file mode 100644 index 0000000000..f9be02119c --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/info/refs @@ -0,0 +1 @@ +5d336c2d72005417e5c84ac691a518a4f053e39b refs/heads/master diff --git a/test/fixtures/repo-copied-file/dot-git/logs/HEAD b/test/fixtures/repo-copied-file/dot-git/logs/HEAD new file mode 100644 index 0000000000..ddbfabb052 --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/logs/HEAD @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 e25ea76910cdc213d19ca4de30f64f54dded0f3b Michelle Tilley 1485376931 -0800 commit (initial): Add one.cc +e25ea76910cdc213d19ca4de30f64f54dded0f3b 5d336c2d72005417e5c84ac691a518a4f053e39b Michelle Tilley 1485376941 -0800 commit (amend): Add one.cc +5d336c2d72005417e5c84ac691a518a4f053e39b 7219822bbcd976b5245f4f37dfdc6243ead0749a Michelle Tilley 1485376979 -0800 commit: Add copied file diff --git a/test/fixtures/repo-copied-file/dot-git/logs/refs/heads/master b/test/fixtures/repo-copied-file/dot-git/logs/refs/heads/master new file mode 100644 index 0000000000..ddbfabb052 --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/logs/refs/heads/master @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 e25ea76910cdc213d19ca4de30f64f54dded0f3b Michelle Tilley 1485376931 -0800 commit (initial): Add one.cc +e25ea76910cdc213d19ca4de30f64f54dded0f3b 5d336c2d72005417e5c84ac691a518a4f053e39b Michelle Tilley 1485376941 -0800 commit (amend): Add one.cc +5d336c2d72005417e5c84ac691a518a4f053e39b 7219822bbcd976b5245f4f37dfdc6243ead0749a Michelle Tilley 1485376979 -0800 commit: Add copied file diff --git a/test/fixtures/repo-copied-file/dot-git/objects/72/19822bbcd976b5245f4f37dfdc6243ead0749a b/test/fixtures/repo-copied-file/dot-git/objects/72/19822bbcd976b5245f4f37dfdc6243ead0749a new file mode 100644 index 0000000000..4bc42d945b Binary files /dev/null and b/test/fixtures/repo-copied-file/dot-git/objects/72/19822bbcd976b5245f4f37dfdc6243ead0749a differ diff --git a/test/fixtures/repo-copied-file/dot-git/objects/9e/7baca78529e5cd097daeea202f5633045e3cdf b/test/fixtures/repo-copied-file/dot-git/objects/9e/7baca78529e5cd097daeea202f5633045e3cdf new file mode 100644 index 0000000000..83bb0c2e53 Binary files /dev/null and b/test/fixtures/repo-copied-file/dot-git/objects/9e/7baca78529e5cd097daeea202f5633045e3cdf differ diff --git a/test/fixtures/repo-copied-file/dot-git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/test/fixtures/repo-copied-file/dot-git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 new file mode 100644 index 0000000000..7112238943 Binary files /dev/null and b/test/fixtures/repo-copied-file/dot-git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 differ diff --git a/test/fixtures/repo-copied-file/dot-git/objects/info/packs b/test/fixtures/repo-copied-file/dot-git/objects/info/packs new file mode 100644 index 0000000000..e3204e1c58 --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/objects/info/packs @@ -0,0 +1,2 @@ +P pack-9a0f2ad2197fb098b6fa2c0ee25a414e21875b0d.pack + diff --git a/test/fixtures/repo-copied-file/dot-git/objects/pack/pack-9a0f2ad2197fb098b6fa2c0ee25a414e21875b0d.idx b/test/fixtures/repo-copied-file/dot-git/objects/pack/pack-9a0f2ad2197fb098b6fa2c0ee25a414e21875b0d.idx new file mode 100644 index 0000000000..11af9cbfc3 Binary files /dev/null and b/test/fixtures/repo-copied-file/dot-git/objects/pack/pack-9a0f2ad2197fb098b6fa2c0ee25a414e21875b0d.idx differ diff --git a/test/fixtures/repo-copied-file/dot-git/objects/pack/pack-9a0f2ad2197fb098b6fa2c0ee25a414e21875b0d.pack b/test/fixtures/repo-copied-file/dot-git/objects/pack/pack-9a0f2ad2197fb098b6fa2c0ee25a414e21875b0d.pack new file mode 100644 index 0000000000..3cfdf5ad38 Binary files /dev/null and b/test/fixtures/repo-copied-file/dot-git/objects/pack/pack-9a0f2ad2197fb098b6fa2c0ee25a414e21875b0d.pack differ diff --git a/test/fixtures/repo-copied-file/dot-git/packed-refs b/test/fixtures/repo-copied-file/dot-git/packed-refs new file mode 100644 index 0000000000..d21cf9e43a --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled +5d336c2d72005417e5c84ac691a518a4f053e39b refs/heads/master diff --git a/test/fixtures/repo-copied-file/dot-git/refs/heads/master b/test/fixtures/repo-copied-file/dot-git/refs/heads/master new file mode 100644 index 0000000000..ebb39bd235 --- /dev/null +++ b/test/fixtures/repo-copied-file/dot-git/refs/heads/master @@ -0,0 +1 @@ +7219822bbcd976b5245f4f37dfdc6243ead0749a diff --git a/test/fixtures/repo-copied-file/one.cc b/test/fixtures/repo-copied-file/one.cc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixtures/repo-copied-file/two.cc b/test/fixtures/repo-copied-file/two.cc new file mode 100644 index 0000000000..a0d39af592 --- /dev/null +++ b/test/fixtures/repo-copied-file/two.cc @@ -0,0 +1,83 @@ +#include "keytar.h" + +#include + +namespace keytar { + +bool AddPassword(const std::string& service, + const std::string& account, + const std::string& password) { + OSStatus status = SecKeychainAddGenericPassword(NULL, + service.length(), + service.data(), + account.length(), + account.data(), + password.length(), + password.data(), + NULL); + return status == errSecSuccess; +} + +bool GetPassword(const std::string& service, + const std::string& account, + std::string* password) { + void *data; + UInt32 length; + OSStatus status = SecKeychainFindGenericPassword(NULL, + service.length(), + service.data(), + account.length(), + account.data(), + &length, + &data, + NULL); + if (status != errSecSuccess) { + return false; + } + + *password = std::string(reinterpret_cast(data), length); + SecKeychainItemFreeContent(NULL, data); + return true; +} + +bool DeletePassword(const std::string& service, const std::string& account) { + SecKeychainItemRef item; + OSStatus status = SecKeychainFindGenericPassword(NULL, + service.length(), + service.data(), + account.length(), + account.data(), + NULL, + NULL, + &item); + if (status != errSecSuccess) + return false; + + status = SecKeychainItemDelete(item); + CFRelease(item); + return status == errSecSuccess; +} + +bool FindPassword(const std::string& service, std::string* password) { + SecKeychainItemRef item; + void *data; + UInt32 length; + + OSStatus status = SecKeychainFindGenericPassword(NULL, + service.length(), + service.data(), + 0, + NULL, + &length, + &data, + &item); + if (status != errSecSuccess) + return false; + + *password = std::string(reinterpret_cast(data), length); + SecKeychainItemFreeContent(NULL, data); + CFRelease(item); + return true; +} + +} // namespace keytar diff --git a/test/git-shell-out-strategy.test.js b/test/git-shell-out-strategy.test.js index b8d1a9b035..1b8cb5d4da 100644 --- a/test/git-shell-out-strategy.test.js +++ b/test/git-shell-out-strategy.test.js @@ -101,6 +101,23 @@ describe('Git commands', function() { assert.deepEqual(mergeConflictFiles, {}); }); + it('displays copied files as an added file', async function() { + // This repo is carefully constructed after much experimentation + // to cause git to detect `two.cc` as a copy of `one.cc`. + const workingDirPath = await cloneRepository('copied-file'); + const git = new GitShellOutStrategy(workingDirPath); + // Undo the last commit, which is where we copied one.cc to two.cc + // and then emptied one.cc. + await git.exec(['reset', '--soft', 'head^']); + const {stagedFiles, unstagedFiles, mergeConflictFiles} = await git.getStatusesForChangedFiles(); + assert.deepEqual(stagedFiles, { + 'one.cc': 'modified', + 'two.cc': 'added', + }); + assert.deepEqual(unstagedFiles, {}); + assert.deepEqual(mergeConflictFiles, {}); + }); + it('returns an object for merge conflict files, including ours/theirs/file status information', async function() { const workingDirPath = await cloneRepository('merge-conflict'); const git = new GitShellOutStrategy(workingDirPath);