implement got_worktree_stage_paths()
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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
diff --git a/include/got_worktree.h b/include/got_worktree.h
index f4f431a..9963b82 100644
--- a/include/got_worktree.h
+++ b/include/got_worktree.h
@@ -371,3 +371,9 @@ const struct got_error *got_worktree_histedit_abort(struct got_worktree *,
/* Get the path to this work tree's histedit script file. */
const struct got_error *got_worktree_get_histedit_script_path(char **,
struct got_worktree *);
+
+/* Stage the specified paths for commit. */
+const struct got_error *got_worktree_stage_paths(struct got_worktree *,
+ struct got_pathlist_head *, struct got_repository *,
+ got_worktree_status_cb, void *,
+ got_worktree_cancel_cb , void *);
diff --git a/lib/fileindex.c b/lib/fileindex.c
index 61af730..dbf735c 100644
--- a/lib/fileindex.c
+++ b/lib/fileindex.c
@@ -161,11 +161,19 @@ got_fileindex_entry_path_len(const struct got_fileindex_entry *ie)
}
uint32_t
-got_fileindex_entry_stage(const struct got_fileindex_entry *ie)
+got_fileindex_entry_stage_get(const struct got_fileindex_entry *ie)
{
return ((ie->flags & GOT_FILEIDX_F_STAGE) >> GOT_FILEIDX_F_STAGE_SHIFT);
}
+void
+got_fileindex_entry_stage_set(struct got_fileindex_entry *ie, uint32_t stage)
+{
+ ie->flags &= ~GOT_FILEIDX_F_STAGE;
+ ie->flags |= ((stage << GOT_FILEIDX_F_STAGE_SHIFT) &
+ GOT_FILEIDX_F_STAGE);
+}
+
int
got_fileindex_entry_has_blob(struct got_fileindex_entry *ie)
{
@@ -379,7 +387,7 @@ write_fileindex_entry(SHA1_CTX *ctx, struct got_fileindex_entry *ie,
if (err)
return err;
- stage = got_fileindex_entry_stage(ie);
+ stage = got_fileindex_entry_stage_get(ie);
if (stage == GOT_FILEIDX_STAGE_MODIFY ||
stage == GOT_FILEIDX_STAGE_ADD) {
SHA1Update(ctx, ie->staged_blob_sha1, SHA1_DIGEST_LENGTH);
@@ -579,7 +587,7 @@ read_fileindex_entry(struct got_fileindex_entry **iep, SHA1_CTX *ctx,
goto done;
if (version >= 2) {
- uint32_t stage = got_fileindex_entry_stage(ie);
+ uint32_t stage = got_fileindex_entry_stage_get(ie);
if (stage == GOT_FILEIDX_STAGE_MODIFY ||
stage == GOT_FILEIDX_STAGE_ADD) {
n = fread(ie->staged_blob_sha1, 1, SHA1_DIGEST_LENGTH,
diff --git a/lib/got_lib_fileindex.h b/lib/got_lib_fileindex.h
index 33b7f14..83e6be7 100644
--- a/lib/got_lib_fileindex.h
+++ b/lib/got_lib_fileindex.h
@@ -156,5 +156,7 @@ const struct got_error *got_fileindex_diff_dir(struct got_fileindex *, DIR *,
int got_fileindex_entry_has_blob(struct got_fileindex_entry *);
int got_fileindex_entry_has_commit(struct got_fileindex_entry *);
int got_fileindex_entry_has_file_on_disk(struct got_fileindex_entry *);
+uint32_t got_fileindex_entry_stage_get(const struct got_fileindex_entry *);
+void got_fileindex_entry_stage_set(struct got_fileindex_entry *ie, uint32_t);
void got_fileindex_entry_mark_deleted_from_disk(struct got_fileindex_entry *);
diff --git a/lib/worktree.c b/lib/worktree.c
index a64b0f8..e2d15ef 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -4856,3 +4856,105 @@ done:
free(commit_ref_name);
return err;
}
+
+static const struct got_error *
+stage_path(const char *path, size_t path_len, struct got_worktree *worktree,
+ struct got_fileindex *fileindex, struct got_repository *repo,
+ got_worktree_status_cb status_cb, void *status_arg)
+{
+ const struct got_error *err = NULL;
+ char *ondisk_path;
+ struct got_fileindex_entry *ie;
+ unsigned char status;
+ struct stat sb;
+ struct got_object_id *blob_id = NULL;
+ uint32_t stage;
+
+ if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, path) == -1)
+ return got_error_from_errno("asprintf");
+
+ ie = got_fileindex_entry_get(fileindex, path, path_len);
+ if (ie == NULL) {
+ err = got_error_path(path, GOT_ERR_FILE_STATUS);
+ goto done;
+ }
+
+ err = get_file_status(&status, &sb, ie, ondisk_path, repo);
+ if (err)
+ goto done;
+
+ switch (status) {
+ case GOT_STATUS_ADD:
+ case GOT_STATUS_MODIFY:
+ err = got_object_blob_create(&blob_id, ondisk_path,
+ repo);
+ if (err)
+ goto done;
+ memcpy(ie->staged_blob_sha1, blob_id->sha1,
+ SHA1_DIGEST_LENGTH);
+ if (status == GOT_STATUS_ADD)
+ stage = GOT_FILEIDX_STAGE_ADD;
+ else
+ stage = GOT_FILEIDX_STAGE_MODIFY;
+ break;
+ case GOT_STATUS_DELETE:
+ stage = GOT_FILEIDX_STAGE_DELETE;
+ break;
+ default:
+ err = got_error_path(path, GOT_ERR_FILE_STATUS);
+ goto done;
+ }
+
+ got_fileindex_entry_stage_set(ie, stage);
+
+ /* XXX TODO pass 'staged' status separately */
+ err = (*status_cb)(status_arg, status, path, blob_id, NULL);
+done:
+ free(blob_id);
+ free(ondisk_path);
+ return err;
+}
+
+const struct got_error *
+got_worktree_stage_paths(struct got_worktree *worktree,
+ struct got_pathlist_head *paths, struct got_repository *repo,
+ got_worktree_status_cb status_cb, void *status_arg,
+ got_worktree_cancel_cb cancel_cb, void *cancel_arg)
+{
+ const struct got_error *err = NULL, *sync_err, *unlockerr;
+ struct got_pathlist_entry *pe;
+ struct got_fileindex *fileindex = NULL;
+ char *fileindex_path = NULL;
+
+ err = lock_worktree(worktree, LOCK_EX);
+ if (err)
+ return err;
+
+ err = open_fileindex(&fileindex, &fileindex_path, worktree);
+ if (err)
+ goto done;
+
+ TAILQ_FOREACH(pe, paths, entry) {
+ if (cancel_cb) {
+ err = (*cancel_cb)(cancel_arg);
+ if (err)
+ break;
+ }
+ err = stage_path(pe->path, pe->path_len, worktree, fileindex,
+ repo, status_cb, status_arg);
+ if (err)
+ break;
+ }
+
+ sync_err = sync_fileindex(fileindex, fileindex_path);
+ if (sync_err && err == NULL)
+ err = sync_err;
+done:
+ free(fileindex_path);
+ if (fileindex)
+ got_fileindex_free(fileindex);
+ unlockerr = lock_worktree(worktree, LOCK_SH);
+ if (unlockerr && err == NULL)
+ err = unlockerr;
+ return err;
+}