commit 0cb83759ff5e9ca28c397bb04edb8e0629eba4bd from: Stefan Sperling date: Sat Aug 03 14:40:05 2019 UTC implement got_worktree_stage_paths() commit - df3352425b599a7ca9e473a9024c6b5333778dc5 commit + 0cb83759ff5e9ca28c397bb04edb8e0629eba4bd blob - f4f431a41a6b1d33399a3974a26880899d231b80 blob + 9963b821c1f57a0322e8913d88df883c8de53679 --- include/got_worktree.h +++ include/got_worktree.h @@ -371,3 +371,9 @@ const struct got_error *got_worktree_histedit_abort(st /* 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 *); blob - 61af730e3e3e103061ccd973a5695d28529aff30 blob + dbf735c60f305ce21773733986a5a067e065d008 --- lib/fileindex.c +++ lib/fileindex.c @@ -161,9 +161,17 @@ got_fileindex_entry_path_len(const struct got_fileinde } 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 @@ -379,7 +387,7 @@ write_fileindex_entry(SHA1_CTX *ctx, struct got_filein 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, 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, blob - 33b7f142cf74b87064731e83d2bfd65101294ff3 blob + 83e6be7d83308583c41892a51e5aa6a7f5bac56c --- lib/got_lib_fileindex.h +++ lib/got_lib_fileindex.h @@ -156,5 +156,7 @@ const struct got_error *got_fileindex_diff_dir(struct 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 *); blob - a64b0f8a733115f6aa705ad8e394e407b54590f8 blob + e2d15ef7a6c7d7222b3bcc4ffe515453b008c1f9 --- lib/worktree.c +++ lib/worktree.c @@ -4854,5 +4854,107 @@ got_worktree_histedit_skip_commit(struct got_worktree err = delete_ref(commit_ref_name, repo); 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; +}