diff --git a/commands.cpp b/commands.cpp index eb44cf0..7d33c68 100644 --- a/commands.cpp +++ b/commands.cpp @@ -461,6 +461,25 @@ static std::pair get_file_attributes (const std::strin return std::make_pair(filter_attr, diff_attr); } +static bool check_if_blob_is_empty (const std::string& object_id) +{ + // git cat-file blob object_id + + std::vector command; + command.push_back("git"); + command.push_back("cat-file"); + command.push_back("blob"); + command.push_back(object_id); + + // TODO: do this more efficiently - don't read entire command output into buffer, only read what we need + std::stringstream output; + if (!successful_exit(exec_command(command, output))) { + throw Error("'git cat-file' failed - is this a Git repository?"); + } + + return output.get() == std::stringstream::traits_type::eof(); +} + static bool check_if_blob_is_encrypted (const std::string& object_id) { // git cat-file blob object_id @@ -1640,7 +1659,8 @@ int status (int argc, const char** argv) if (file_attrs.first == "git-crypt" || std::strncmp(file_attrs.first.c_str(), "git-crypt-", 10) == 0) { // File is encrypted - const bool blob_is_unencrypted = !object_id.empty() && !check_if_blob_is_encrypted(object_id); + // If the file is empty, don't consider it unencrypted, because in newly-initialized repos (specifically those with keys with skip_empty set) we don't encrypt empty files. Unfortunately, we can't easily determine here if the key has skip_empty set, so just act like it is. This means we won't notice if an old repo has an empty unencrypted file that should be encrypted. Fortunately, this isn't really a big deal because empty files obviously don't contain anything sensitive in them. + const bool blob_is_unencrypted = !object_id.empty() && !check_if_blob_is_encrypted(object_id) && !check_if_blob_is_empty(object_id); if (fix_problems && blob_is_unencrypted) { if (access(filename.c_str(), F_OK) != 0) {