In 8e2dc6ac06 (commit: give final warning when reattaching HEAD to leave commits behind, 2011-02-18) we introduced orphaned_commit_warning() in builtin/checkout.c. In subsequent commits we're going to use orphaned_commit_warning() not only from builtin/checkout.c, but from other builtin commands too. Let's move the function and its helpers to checkout.c and make it an API callable not just from builtin/checkout.c. Signed-off-by: Rubén Justo <rjusto@xxxxxxxxx> --- builtin/checkout.c | 124 ------------------------------------------- checkout.c | 129 +++++++++++++++++++++++++++++++++++++++++++++ checkout.h | 9 ++++ 3 files changed, 138 insertions(+), 124 deletions(-) diff --git a/builtin/checkout.c b/builtin/checkout.c index 6f5d82ed3d..991413ef1a 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -656,24 +656,6 @@ static void show_local_changes(struct object *head, release_revisions(&rev); } -static void describe_detached_head(const char *msg, struct commit *commit) -{ - struct strbuf sb = STRBUF_INIT; - - if (!repo_parse_commit(the_repository, commit)) - pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb); - if (print_sha1_ellipsis()) { - fprintf(stderr, "%s %s... %s\n", msg, - repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV), - sb.buf); - } else { - fprintf(stderr, "%s %s %s\n", msg, - repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV), - sb.buf); - } - strbuf_release(&sb); -} - static int reset_tree(struct tree *tree, const struct checkout_opts *o, int worktree, int *writeout_error, struct branch_info *info) @@ -1016,112 +998,6 @@ static void update_refs_for_switch(const struct checkout_opts *opts, report_tracking(new_branch_info); } -static int add_pending_uninteresting_ref(const char *refname, - const struct object_id *oid, - int flags UNUSED, void *cb_data) -{ - add_pending_oid(cb_data, refname, oid, UNINTERESTING); - return 0; -} - -static void describe_one_orphan(struct strbuf *sb, struct commit *commit) -{ - strbuf_addstr(sb, " "); - strbuf_add_unique_abbrev(sb, &commit->object.oid, DEFAULT_ABBREV); - strbuf_addch(sb, ' '); - if (!repo_parse_commit(the_repository, commit)) - pp_commit_easy(CMIT_FMT_ONELINE, commit, sb); - strbuf_addch(sb, '\n'); -} - -#define ORPHAN_CUTOFF 4 -static void suggest_reattach(struct commit *commit, struct rev_info *revs) -{ - struct commit *c, *last = NULL; - struct strbuf sb = STRBUF_INIT; - int lost = 0; - while ((c = get_revision(revs)) != NULL) { - if (lost < ORPHAN_CUTOFF) - describe_one_orphan(&sb, c); - last = c; - lost++; - } - if (ORPHAN_CUTOFF < lost) { - int more = lost - ORPHAN_CUTOFF; - if (more == 1) - describe_one_orphan(&sb, last); - else - strbuf_addf(&sb, _(" ... and %d more.\n"), more); - } - - fprintf(stderr, - Q_( - /* The singular version */ - "Warning: you are leaving %d commit behind, " - "not connected to\n" - "any of your branches:\n\n" - "%s\n", - /* The plural version */ - "Warning: you are leaving %d commits behind, " - "not connected to\n" - "any of your branches:\n\n" - "%s\n", - /* Give ngettext() the count */ - lost), - lost, - sb.buf); - strbuf_release(&sb); - - if (advice_enabled(ADVICE_DETACHED_HEAD)) - fprintf(stderr, - Q_( - /* The singular version */ - "If you want to keep it by creating a new branch, " - "this may be a good time\nto do so with:\n\n" - " git branch <new-branch-name> %s\n\n", - /* The plural version */ - "If you want to keep them by creating a new branch, " - "this may be a good time\nto do so with:\n\n" - " git branch <new-branch-name> %s\n\n", - /* Give ngettext() the count */ - lost), - repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV)); -} - -/* - * We are about to leave commit that was at the tip of a detached - * HEAD. If it is not reachable from any ref, this is the last chance - * for the user to do so without resorting to reflog. - */ -static void orphaned_commit_warning(struct commit *old_commit, struct commit *new_commit) -{ - struct rev_info revs; - struct object *object = &old_commit->object; - - repo_init_revisions(the_repository, &revs, NULL); - setup_revisions(0, NULL, &revs, NULL); - - object->flags &= ~UNINTERESTING; - add_pending_object(&revs, object, oid_to_hex(&object->oid)); - - for_each_ref(add_pending_uninteresting_ref, &revs); - if (new_commit) - add_pending_oid(&revs, "HEAD", - &new_commit->object.oid, - UNINTERESTING); - - if (prepare_revision_walk(&revs)) - die(_("internal error in revision walk")); - if (!(old_commit->object.flags & UNINTERESTING)) - suggest_reattach(old_commit, &revs); - else - describe_detached_head(_("Previous HEAD position was"), old_commit); - - /* Clean up objects used, as they will be reused. */ - repo_clear_commit_marks(the_repository, ALL_REV_FLAGS); - release_revisions(&revs); -} - static int switch_branches(const struct checkout_opts *opts, struct branch_info *new_branch_info) { diff --git a/checkout.c b/checkout.c index 04238b2713..18e7362043 100644 --- a/checkout.c +++ b/checkout.c @@ -5,6 +5,11 @@ #include "checkout.h" #include "config.h" #include "strbuf.h" +#include "environment.h" +#include "revision.h" +#include "advice.h" +#include "hex.h" +#include "refs.h" struct tracking_name_data { /* const */ char *src_ref; @@ -70,3 +75,127 @@ const char *unique_tracking_name(const char *name, struct object_id *oid, } return NULL; } + +void describe_detached_head(const char *msg, struct commit *commit) +{ + struct strbuf sb = STRBUF_INIT; + + if (!repo_parse_commit(the_repository, commit)) + pp_commit_easy(CMIT_FMT_ONELINE, commit, &sb); + if (print_sha1_ellipsis()) { + fprintf(stderr, "%s %s... %s\n", msg, + repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV), + sb.buf); + } else { + fprintf(stderr, "%s %s %s\n", msg, + repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV), + sb.buf); + } + strbuf_release(&sb); +} + +static int add_pending_uninteresting_ref(const char *refname, + const struct object_id *oid, + int flags UNUSED, void *cb_data) +{ + add_pending_oid(cb_data, refname, oid, UNINTERESTING); + return 0; +} + +static void describe_one_orphan(struct strbuf *sb, struct commit *commit) +{ + strbuf_addstr(sb, " "); + strbuf_add_unique_abbrev(sb, &commit->object.oid, DEFAULT_ABBREV); + strbuf_addch(sb, ' '); + if (!repo_parse_commit(the_repository, commit)) + pp_commit_easy(CMIT_FMT_ONELINE, commit, sb); + strbuf_addch(sb, '\n'); +} + +#define ORPHAN_CUTOFF 4 +static void suggest_reattach(struct commit *commit, struct rev_info *revs) +{ + struct commit *c, *last = NULL; + struct strbuf sb = STRBUF_INIT; + int lost = 0; + while ((c = get_revision(revs)) != NULL) { + if (lost < ORPHAN_CUTOFF) + describe_one_orphan(&sb, c); + last = c; + lost++; + } + if (ORPHAN_CUTOFF < lost) { + int more = lost - ORPHAN_CUTOFF; + if (more == 1) + describe_one_orphan(&sb, last); + else + strbuf_addf(&sb, _(" ... and %d more.\n"), more); + } + + fprintf(stderr, + Q_( + /* The singular version */ + "Warning: you are leaving %d commit behind, " + "not connected to\n" + "any of your branches:\n\n" + "%s\n", + /* The plural version */ + "Warning: you are leaving %d commits behind, " + "not connected to\n" + "any of your branches:\n\n" + "%s\n", + /* Give ngettext() the count */ + lost), + lost, + sb.buf); + strbuf_release(&sb); + + if (advice_enabled(ADVICE_DETACHED_HEAD)) + fprintf(stderr, + Q_( + /* The singular version */ + "If you want to keep it by creating a new branch, " + "this may be a good time\nto do so with:\n\n" + " git branch <new-branch-name> %s\n\n", + /* The plural version */ + "If you want to keep them by creating a new branch, " + "this may be a good time\nto do so with:\n\n" + " git branch <new-branch-name> %s\n\n", + /* Give ngettext() the count */ + lost), + repo_find_unique_abbrev(the_repository, &commit->object.oid, DEFAULT_ABBREV)); +} + +/* + * We are about to leave commit that was at the tip of a detached + * HEAD. If it is not reachable from any ref, this is the last chance + * for the user to do so without resorting to reflog. + */ +void orphaned_commit_warning(struct commit *old_commit, struct commit *new_commit) +{ + struct rev_info revs; + struct object *object = &old_commit->object; + + repo_init_revisions(the_repository, &revs, NULL); + setup_revisions(0, NULL, &revs, NULL); + + object->flags &= ~UNINTERESTING; + add_pending_object(&revs, object, oid_to_hex(&object->oid)); + + for_each_ref(add_pending_uninteresting_ref, &revs); + if (new_commit) + add_pending_oid(&revs, "HEAD", + &new_commit->object.oid, + UNINTERESTING); + + if (prepare_revision_walk(&revs)) + die(_("internal error in revision walk")); + if (!(old_commit->object.flags & UNINTERESTING)) + suggest_reattach(old_commit, &revs); + else + describe_detached_head(_("Previous HEAD position was"), old_commit); + + /* Clean up objects used, as they will be reused. */ + repo_clear_commit_marks(the_repository, ALL_REV_FLAGS); + release_revisions(&revs); +} diff --git a/checkout.h b/checkout.h index 1917f3b323..c7dc056544 100644 --- a/checkout.h +++ b/checkout.h @@ -2,6 +2,7 @@ #define CHECKOUT_H #include "hash.h" +#include "commit.h" /* * Check if the branch name uniquely matches a branch name on a remote @@ -12,4 +13,12 @@ const char *unique_tracking_name(const char *name, struct object_id *oid, int *dwim_remotes_matched); +/* + * We are about to leave commit that was at the tip of a detached + * HEAD. If it is not reachable from any ref, this is the last chance + * for the user to do so without resorting to reflog. + */ +void orphaned_commit_warning(struct commit *old_commit, struct commit *new_commit); + +void describe_detached_head(const char *msg, struct commit *commit); #endif /* CHECKOUT_H */ -- 2.39.2