commit - 35c965b2755aaf9dc232228d76d19cb2e8907d9a
commit + be7061eb8834a24d83d6376aa2586e1b3e2232ab
blob - 9e9dfd9ecd25f2570ce974d906a9f376a022448d
blob + 74a744a651a7a4f591fd5c53a0724ec69fbce4bd
--- got/got.c
+++ got/got.c
}
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;
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
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
#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;
{ 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
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
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 *