| 1012 | out << " or: git-crypt unlock KEY_FILE ..." << std::endl; |
| 1013 | } |
| 1014 | int unlock (int argc, const char** argv) |
| 1015 | { |
| 1016 | // 1. Make sure working directory is clean (ignoring untracked files) |
| 1017 | // We do this because we check out files later, and we don't want the |
| 1018 | // user to lose any changes. (TODO: only care if encrypted files are |
| 1019 | // modified, since we only check out encrypted files) |
| 1020 | |
| 1021 | // Running 'git status' also serves as a check that the Git repo is accessible. |
| 1022 | |
| 1023 | std::stringstream status_output; |
| 1024 | get_git_status(status_output); |
| 1025 | if (status_output.peek() != -1) { |
| 1026 | std::clog << "Error: Working directory not clean." << std::endl; |
| 1027 | std::clog << "Please commit your changes or 'git stash' them before running 'git-crypt unlock'." << std::endl; |
| 1028 | return 1; |
| 1029 | } |
| 1030 | |
| 1031 | // 2. Load the key(s) |
| 1032 | std::vector<Key_file> key_files; |
| 1033 | if (argc > 0) { |
| 1034 | // Read from the symmetric key file(s) |
| 1035 | |
| 1036 | for (int argi = 0; argi < argc; ++argi) { |
| 1037 | const char* symmetric_key_file = argv[argi]; |
| 1038 | Key_file key_file; |
| 1039 | |
| 1040 | try { |
| 1041 | if (std::strcmp(symmetric_key_file, "-") == 0) { |
| 1042 | key_file.load(std::cin); |
| 1043 | } else { |
| 1044 | if (!key_file.load_from_file(symmetric_key_file)) { |
| 1045 | std::clog << "Error: " << symmetric_key_file << ": unable to read key file" << std::endl; |
| 1046 | return 1; |
| 1047 | } |
| 1048 | } |
| 1049 | } catch (Key_file::Incompatible) { |
| 1050 | std::clog << "Error: " << symmetric_key_file << " is in an incompatible format" << std::endl; |
| 1051 | std::clog << "Please upgrade to a newer version of git-crypt." << std::endl; |
| 1052 | return 1; |
| 1053 | } catch (Key_file::Malformed) { |
| 1054 | std::clog << "Error: " << symmetric_key_file << ": not a valid git-crypt key file" << std::endl; |
| 1055 | std::clog << "If this key was created prior to git-crypt 0.4, you need to migrate it" << std::endl; |
| 1056 | std::clog << "by running 'git-crypt migrate-key /path/to/old_key /path/to/migrated_key'." << std::endl; |
| 1057 | return 1; |
| 1058 | } |
| 1059 | |
| 1060 | key_files.push_back(key_file); |
| 1061 | } |
| 1062 | } else { |
| 1063 | // Decrypt GPG key from root of repo |
| 1064 | std::string repo_keys_path(get_repo_keys_path()); |
| 1065 | std::vector<std::string> gpg_secret_keys(gpg_list_secret_keys()); |
| 1066 | // TODO: command-line option to specify the precise secret key to use |
| 1067 | // TODO: don't hard code key version 0 here - instead, determine the most recent version and try to decrypt that, or decrypt all versions if command-line option specified |
| 1068 | // TODO: command line option to only unlock specific key instead of all of them |
| 1069 | // TODO: avoid decrypting repo keys which are already unlocked in the .git directory |
| 1070 | if (!decrypt_repo_keys(key_files, 0, gpg_secret_keys, repo_keys_path)) { |
| 1071 | std::clog << "Error: no GPG secret key available to unlock this repository." << std::endl; |
no test coverage detected