commit be7061eb8834a24d83d6376aa2586e1b3e2232ab from: Stefan Sperling date: Sun Dec 30 16:30:42 2018 UTC ensure that 'got update' stays on the current branch commit - 35c965b2755aaf9dc232228d76d19cb2e8907d9a commit + be7061eb8834a24d83d6376aa2586e1b3e2232ab blob - 9e9dfd9ecd25f2570ce974d906a9f376a022448d blob + 74a744a651a7a4f591fd5c53a0724ec69fbce4bd --- got/got.c +++ got/got.c @@ -329,6 +329,63 @@ update_progress(void *arg, unsigned char status, const } static const struct got_error * +check_ancestry(struct got_worktree *worktree, struct got_object_id *commit_id, + struct got_repository *repo) +{ + const struct got_error *err; + struct got_reference *head_ref = NULL; + struct got_object_id *head_commit_id = NULL; + struct got_commit_graph *graph = NULL; + + head_ref = got_worktree_get_head_ref(worktree); + if (head_ref == NULL) + return got_error_from_errno(); + + err = got_ref_resolve(&head_commit_id, repo, head_ref); + if (err) + goto done; + + err = got_commit_graph_open(&graph, head_commit_id, "/", 1, repo); + if (err) + goto done; + + err = got_commit_graph_iter_start(graph, head_commit_id, repo); + if (err) + goto done; + while (1) { + struct got_object_id *id; + + if (sigint_received || sigpipe_received) + break; + + err = got_commit_graph_iter_next(&id, graph); + if (err) { + if (err->code == GOT_ERR_ITER_COMPLETED) { + err = got_error(GOT_ERR_ANCESTRY); + break; + } + if (err->code != GOT_ERR_ITER_NEED_MORE) + break; + err = got_commit_graph_fetch_commits(graph, 1, repo); + if (err) + break; + else + continue; + } + if (id == NULL) + break; + if (got_object_id_cmp(id, commit_id) == 0) + break; + } +done: + if (head_ref) + got_ref_close(head_ref); + if (graph) + got_commit_graph_close(graph); + return err; +} + +static const struct got_error * cmd_update(int argc, char *argv[]) { const struct got_error *error = NULL; @@ -396,7 +453,9 @@ cmd_update(int argc, char *argv[]) goto done; } - /* TODO: Ensure that we are staying on the current branch. */ + error = check_ancestry(worktree, commit_id, repo); + if (error != NULL) + goto done; if (got_object_id_cmp(got_worktree_get_base_commit_id(worktree), commit_id) != 0) { blob - 065409662149bcf0dd01a8ce82c8989d096cefd7 blob + 19df8926d7f0feb219d5f654a077dac2f6110760 --- include/got_commit_graph.h +++ include/got_commit_graph.h @@ -28,3 +28,6 @@ const struct got_error *got_commit_graph_iter_start( struct got_commit_graph *, struct got_object_id *, struct got_repository *); const struct got_error *got_commit_graph_iter_next(struct got_object_id **, struct got_commit_graph *); +const struct got_error *got_commit_graph_intersect(struct got_object_id **, + struct got_commit_graph *, struct got_commit_graph *, + struct got_repository *); blob - 7720ed223a4d642bf1479c1aed2af411b2dadc87 blob + 34bd324b68b53131fb06adc2a13b17f6a601bc78 --- include/got_error.h +++ include/got_error.h @@ -68,6 +68,7 @@ #define GOT_ERR_FILEIDX_VER 52 #define GOT_ERR_FILEIDX_CSUM 53 #define GOT_ERR_PATH_PREFIX 54 +#define GOT_ERR_ANCESTRY 55 static const struct got_error { int code; @@ -125,6 +126,8 @@ static const struct got_error { { GOT_ERR_FILEIDX_CSUM, "bad file index checksum" }, { GOT_ERR_PATH_PREFIX, "worktree already contains items from a " "different path prefix" }, + { GOT_ERR_ANCESTRY, "specified commit does not share ancestry with " + "the current branch" }, }; /* blob - 43411d61291f20f6d25f20ec303368bac36730c1 blob + 1424a427f623a992ad42ee5b418df6c7f7b3c687 --- include/got_worktree.h +++ include/got_worktree.h @@ -64,6 +64,12 @@ const struct got_error *got_worktree_match_path_prefix char *got_worktree_get_head_ref_name(struct got_worktree *); /* + * Get the work tree's HEAD reference. + * The caller must dispose of it with free(3). + */ +struct got_reference *got_worktree_get_head_ref(struct got_worktree *); + +/* * Get the current base commit ID of a worktree. */ const struct got_object_id *got_worktree_get_base_commit_id(struct got_worktree *); blob - 67ce5a4496764e165e3247162f316282aa5b2736 blob + 94e0615878acd046d8424d079eb4ad72548eee1d --- lib/worktree.c +++ lib/worktree.c @@ -439,6 +439,12 @@ char * got_worktree_get_head_ref_name(struct got_worktree *worktree) { return got_ref_to_str(worktree->head_ref); +} + +struct got_reference * +got_worktree_get_head_ref(struct got_worktree *worktree) +{ + return got_ref_dup(worktree->head_ref); } const struct got_object_id *