fix perms in committed tree entries
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
diff --git a/lib/worktree.c b/lib/worktree.c
index d2d1a1e..e384ebc 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -2217,15 +2217,18 @@ done:
struct commitable {
char *path;
+ char *ondisk_path;
unsigned char status;
struct got_object_id *id;
struct got_object_id *base_id;
+ mode_t mode;
};
static void
free_commitable(struct commitable *ct)
{
free(ct->path);
+ free(ct->ondisk_path);
free(ct->id);
free(ct->base_id);
free(ct);
@@ -2246,6 +2249,7 @@ collect_commitables(void *arg, unsigned char status, const char *relpath,
struct commitable *ct = NULL;
struct got_pathlist_entry *new = NULL;
char *parent_path = NULL, *path = NULL;
+ struct stat sb;
if (status == GOT_STATUS_CONFLICT)
return got_error(GOT_ERR_COMMIT_CONFLICT);
@@ -2274,6 +2278,21 @@ collect_commitables(void *arg, unsigned char status, const char *relpath,
goto done;
}
+ if (asprintf(&ct->ondisk_path, "%s/%s", a->worktree->root_path,
+ relpath) == -1) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ if (status == GOT_STATUS_DELETE) {
+ sb.st_mode = GOT_DEFAULT_FILE_MODE;
+ } else {
+ if (lstat(ct->ondisk_path, &sb) != 0) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ ct->mode = sb.st_mode;
+ }
+
ct->status = status;
ct->id = NULL; /* will be filled in when blob gets created */
if (ct->status != GOT_STATUS_ADD) {
@@ -2351,6 +2370,12 @@ match_ct_parent_path(int *match, struct commitable *ct, const char *path)
return err;
}
+static mode_t
+get_ct_file_mode(struct commitable *ct)
+{
+ return S_IFREG | (ct->mode & ((S_IRWXU | S_IRWXG | S_IRWXO)));
+}
+
static const struct got_error *
alloc_modified_blob_tree_entry(struct got_tree_entry **new_te,
struct got_tree_entry *te, struct commitable *ct)
@@ -2363,8 +2388,7 @@ alloc_modified_blob_tree_entry(struct got_tree_entry **new_te,
if (err)
goto done;
- /* XXX TODO: update mode from disk (derive from ct?)! */
- (*new_te)->mode = GOT_DEFAULT_FILE_MODE;
+ (*new_te)->mode = get_ct_file_mode(ct);
free((*new_te)->id);
(*new_te)->id = got_object_id_dup(ct->id);
@@ -2404,8 +2428,7 @@ alloc_added_blob_tree_entry(struct got_tree_entry **new_te,
goto done;
}
- /* XXX TODO: update mode from disk (derive from ct?)! */
- (*new_te)->mode = GOT_DEFAULT_FILE_MODE;
+ (*new_te)->mode = get_ct_file_mode(ct);
(*new_te)->id = got_object_id_dup(ct->id);
if ((*new_te)->id == NULL) {
@@ -2538,7 +2561,7 @@ write_tree(struct got_object_id **new_tree_id,
*slash = '\0'; /* trim trailing path components */
new_te = calloc(1, sizeof(*new_te));
- new_te->mode = GOT_DEFAULT_DIR_MODE;
+ new_te->mode = S_IFDIR;
new_te->name = strdup(child_path);
if (new_te->name == NULL) {
got_object_tree_entry_close(new_te);
@@ -2658,13 +2681,6 @@ update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
TAILQ_FOREACH(pe, commitable_paths, entry) {
struct got_fileindex_entry *ie;
struct commitable *ct = pe->data;
- char *ondisk_path;
-
- if (asprintf(&ondisk_path, "%s/%s",
- worktree->root_path, pe->path) == -1) {
- err = got_error_from_errno();
- goto done;
- }
ie = got_fileindex_entry_get(fileindex, pe->path);
if (ie) {
@@ -2673,11 +2689,11 @@ update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
got_fileindex_entry_free(ie);
} else
err = got_fileindex_entry_update(ie,
- ondisk_path, ct->id->sha1,
+ ct->ondisk_path, ct->id->sha1,
new_base_commit_id->sha1, 1);
} else {
err = got_fileindex_entry_alloc(&ie,
- ondisk_path, pe->path, ct->id->sha1,
+ ct->ondisk_path, pe->path, ct->id->sha1,
new_base_commit_id->sha1);
if (err)
goto done;
@@ -2685,7 +2701,6 @@ update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
if (err)
goto done;
}
- free(ondisk_path);
}
err = got_fileindex_write(fileindex, new_index);