summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cache-tree.c5
-rw-r--r--cache.h1
-rw-r--r--object-file.c20
-rw-r--r--object-store.h10
-rwxr-xr-xt/t0004-unwritable.sh47
5 files changed, 67 insertions, 16 deletions
diff --git a/cache-tree.c b/cache-tree.c
index 90919f9e34..f21bfc631c 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -440,8 +440,9 @@ static int update_one(struct cache_tree *it,
} else if (dryrun) {
hash_object_file(the_hash_algo, buffer.buf, buffer.len,
tree_type, &it->oid);
- } else if (write_object_file(buffer.buf, buffer.len, tree_type,
- &it->oid)) {
+ } else if (write_object_file_flags(buffer.buf, buffer.len, tree_type,
+ &it->oid, flags & WRITE_TREE_SILENT
+ ? HASH_SILENT : 0)) {
strbuf_release(&buffer);
return -1;
}
diff --git a/cache.h b/cache.h
index acb67dbd64..eba12487b9 100644
--- a/cache.h
+++ b/cache.h
@@ -887,6 +887,7 @@ int ie_modified(struct index_state *, const struct cache_entry *, struct stat *,
#define HASH_WRITE_OBJECT 1
#define HASH_FORMAT_CHECK 2
#define HASH_RENORMALIZE 4
+#define HASH_SILENT 8
int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
diff --git a/object-file.c b/object-file.c
index b3e1718885..02b7970274 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1862,7 +1862,7 @@ static int create_tmpfile(struct strbuf *tmp, const char *filename)
static int write_loose_object(const struct object_id *oid, char *hdr,
int hdrlen, const void *buf, unsigned long len,
- time_t mtime)
+ time_t mtime, unsigned flags)
{
int fd, ret;
unsigned char compressed[4096];
@@ -1876,7 +1876,9 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
fd = create_tmpfile(&tmp_file, filename.buf);
if (fd < 0) {
- if (errno == EACCES)
+ if (flags & HASH_SILENT)
+ return -1;
+ else if (errno == EACCES)
return error(_("insufficient permission for adding an object to repository database %s"), get_object_directory());
else
return error_errno(_("unable to create temporary file"));
@@ -1926,7 +1928,8 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
struct utimbuf utb;
utb.actime = mtime;
utb.modtime = mtime;
- if (utime(tmp_file.buf, &utb) < 0)
+ if (utime(tmp_file.buf, &utb) < 0 &&
+ !(flags & HASH_SILENT))
warning_errno(_("failed utime() on %s"), tmp_file.buf);
}
@@ -1951,8 +1954,9 @@ static int freshen_packed_object(const struct object_id *oid)
return 1;
}
-int write_object_file(const void *buf, unsigned long len, const char *type,
- struct object_id *oid)
+int write_object_file_flags(const void *buf, unsigned long len,
+ const char *type, struct object_id *oid,
+ unsigned flags)
{
char hdr[MAX_HEADER_LEN];
int hdrlen = sizeof(hdr);
@@ -1964,7 +1968,7 @@ int write_object_file(const void *buf, unsigned long len, const char *type,
&hdrlen);
if (freshen_packed_object(oid) || freshen_loose_object(oid))
return 0;
- return write_loose_object(oid, hdr, hdrlen, buf, len, 0);
+ return write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags);
}
int hash_object_file_literally(const void *buf, unsigned long len,
@@ -1984,7 +1988,7 @@ int hash_object_file_literally(const void *buf, unsigned long len,
goto cleanup;
if (freshen_packed_object(oid) || freshen_loose_object(oid))
goto cleanup;
- status = write_loose_object(oid, header, hdrlen, buf, len, 0);
+ status = write_loose_object(oid, header, hdrlen, buf, len, 0, 0);
cleanup:
free(header);
@@ -2006,7 +2010,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
if (!buf)
return error(_("cannot read object for %s"), oid_to_hex(oid));
hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1;
- ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime);
+ ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0);
free(buf);
return ret;
diff --git a/object-store.h b/object-store.h
index 07387dc48f..952efb6a4b 100644
--- a/object-store.h
+++ b/object-store.h
@@ -223,8 +223,14 @@ int hash_object_file(const struct git_hash_algo *algo, const void *buf,
unsigned long len, const char *type,
struct object_id *oid);
-int write_object_file(const void *buf, unsigned long len,
- const char *type, struct object_id *oid);
+int write_object_file_flags(const void *buf, unsigned long len,
+ const char *type, struct object_id *oid,
+ unsigned flags);
+static inline int write_object_file(const void *buf, unsigned long len,
+ const char *type, struct object_id *oid)
+{
+ return write_object_file_flags(buf, len, type, oid, 0);
+}
int hash_object_file_literally(const void *buf, unsigned long len,
const char *type, struct object_id *oid,
diff --git a/t/t0004-unwritable.sh b/t/t0004-unwritable.sh
index 37d68ef03b..2e9d652d82 100755
--- a/t/t0004-unwritable.sh
+++ b/t/t0004-unwritable.sh
@@ -19,27 +19,66 @@ test_expect_success setup '
test_expect_success POSIXPERM,SANITY 'write-tree should notice unwritable repository' '
test_when_finished "chmod 775 .git/objects .git/objects/??" &&
chmod a-w .git/objects .git/objects/?? &&
- test_must_fail git write-tree
+ test_must_fail git write-tree 2>out.write-tree
+'
+
+test_lazy_prereq WRITE_TREE_OUT 'test -e "$TRASH_DIRECTORY"/out.write-tree'
+test_expect_success WRITE_TREE_OUT 'write-tree output on unwritable repository' '
+ cat >expect <<-\EOF &&
+ error: insufficient permission for adding an object to repository database .git/objects
+ fatal: git-write-tree: error building trees
+ EOF
+ test_cmp expect out.write-tree
'
test_expect_success POSIXPERM,SANITY,!SANITIZE_LEAK 'commit should notice unwritable repository' '
test_when_finished "chmod 775 .git/objects .git/objects/??" &&
chmod a-w .git/objects .git/objects/?? &&
- test_must_fail git commit -m second
+ test_must_fail git commit -m second 2>out.commit
+'
+
+test_lazy_prereq COMMIT_OUT 'test -e "$TRASH_DIRECTORY"/out.commit'
+test_expect_success COMMIT_OUT 'commit output on unwritable repository' '
+ cat >expect <<-\EOF &&
+ error: insufficient permission for adding an object to repository database .git/objects
+ error: Error building trees
+ EOF
+ test_cmp expect out.commit
'
test_expect_success POSIXPERM,SANITY 'update-index should notice unwritable repository' '
test_when_finished "chmod 775 .git/objects .git/objects/??" &&
echo 6O >file &&
chmod a-w .git/objects .git/objects/?? &&
- test_must_fail git update-index file
+ test_must_fail git update-index file 2>out.update-index
+'
+
+test_lazy_prereq UPDATE_INDEX_OUT 'test -e "$TRASH_DIRECTORY"/out.update-index'
+test_expect_success UPDATE_INDEX_OUT 'update-index output on unwritable repository' '
+ cat >expect <<-\EOF &&
+ error: insufficient permission for adding an object to repository database .git/objects
+ error: file: failed to insert into database
+ fatal: Unable to process path file
+ EOF
+ test_cmp expect out.update-index
'
test_expect_success POSIXPERM,SANITY 'add should notice unwritable repository' '
test_when_finished "chmod 775 .git/objects .git/objects/??" &&
echo b >file &&
chmod a-w .git/objects .git/objects/?? &&
- test_must_fail git add file
+ test_must_fail git add file 2>out.add
+'
+
+test_lazy_prereq ADD_OUT 'test -e "$TRASH_DIRECTORY"/out.add'
+test_expect_success ADD_OUT 'add output on unwritable repository' '
+ cat >expect <<-\EOF &&
+ error: insufficient permission for adding an object to repository database .git/objects
+ error: file: failed to insert into database
+ error: unable to index file '\''file'\''
+ fatal: updating files failed
+ EOF
+ test_cmp expect out.add
'
test_done