checkout: print something when checking out paths
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Tue, 13 Nov 2018 18:28:00 +0000 (19:28 +0100)
committerJunio C Hamano <gitster@pobox.com>
Wed, 14 Nov 2018 06:10:35 +0000 (15:10 +0900)
One of the problems with "git checkout" is that it does so many
different things and could confuse people specially when we fail to
handle ambiguation correctly.

One way to help with that is tell the user what sort of operation is
actually carried out. When switching branches, we always print
something unless --quiet, either

- "HEAD is now at ..."
- "Reset branch ..."
- "Already on ..."
- "Switched to and reset ..."
- "Switched to a new branch ..."
- "Switched to branch ..."

Checking out paths however is silent. Print something so that if we
got the user intention wrong, they won't waste too much time to find
that out. For the remaining cases of checkout we now print either

- "Checked out ... paths out of the index"
- "Checked out ... paths out of <abbrev hash>"

Since the purpose of printing this is to help disambiguate. Only do it
when "--" is missing.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
apply.c
builtin/checkout-index.c
builtin/checkout.c
builtin/difftool.c
cache.h
entry.c
unpack-trees.c
diff --git a/apply.c b/apply.c
index 073d5f04512ac6febc2949040f53ef273433f3c0..5876b021972e745f586214bf522cc6a8ad1d54f8 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -3352,7 +3352,8 @@ static int checkout_target(struct index_state *istate,
 
        costate.refresh_cache = 1;
        costate.istate = istate;
-       if (checkout_entry(ce, &costate, NULL) || lstat(ce->name, st))
+       if (checkout_entry(ce, &costate, NULL, NULL) ||
+           lstat(ce->name, st))
                return error(_("cannot checkout %s"), ce->name);
        return 0;
 }
index 88b86c8d9f5a0ea9c49b42e891082203b80a977f..bada491f5808db38a34ad40fae19bd780aa3354c 100644 (file)
@@ -67,7 +67,8 @@ static int checkout_file(const char *name, const char *prefix)
                        continue;
                did_checkout = 1;
                if (checkout_entry(ce, &state,
-                   to_tempfile ? topath[ce_stage(ce)] : NULL) < 0)
+                                  to_tempfile ? topath[ce_stage(ce)] : NULL,
+                                  NULL) < 0)
                        errs++;
        }
 
@@ -111,7 +112,8 @@ static void checkout_all(const char *prefix, int prefix_length)
                                write_tempfile_record(last_ce->name, prefix);
                }
                if (checkout_entry(ce, &state,
-                   to_tempfile ? topath[ce_stage(ce)] : NULL) < 0)
+                                  to_tempfile ? topath[ce_stage(ce)] : NULL,
+                                  NULL) < 0)
                        errs++;
                last_ce = ce;
        }
index acdafc6e4c4d104aadcbe7492a8045e16e83ba50..3a0b86ec1c86f11608c9a9772cbcf7412dc9fb52 100644 (file)
@@ -44,6 +44,7 @@ struct checkout_opts {
        int ignore_skipworktree;
        int ignore_other_worktrees;
        int show_progress;
+       int count_checkout_paths;
        /*
         * If new checkout options are added, skip_merge_working_tree
         * should be updated accordingly.
@@ -165,12 +166,13 @@ static int check_stages(unsigned stages, const struct cache_entry *ce, int pos)
 }
 
 static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
-                         const struct checkout *state)
+                         const struct checkout *state, int *nr_checkouts)
 {
        while (pos < active_nr &&
               !strcmp(active_cache[pos]->name, ce->name)) {
                if (ce_stage(active_cache[pos]) == stage)
-                       return checkout_entry(active_cache[pos], state, NULL);
+                       return checkout_entry(active_cache[pos], state,
+                                             NULL, nr_checkouts);
                pos++;
        }
        if (stage == 2)
@@ -179,7 +181,7 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
                return error(_("path '%s' does not have their version"), ce->name);
 }
 
-static int checkout_merged(int pos, const struct checkout *state)
+static int checkout_merged(int pos, const struct checkout *state, int *nr_checkouts)
 {
        struct cache_entry *ce = active_cache[pos];
        const char *path = ce->name;
@@ -242,7 +244,7 @@ static int checkout_merged(int pos, const struct checkout *state)
        ce = make_transient_cache_entry(mode, &oid, path, 2);
        if (!ce)
                die(_("make_cache_entry failed for path '%s'"), path);
-       status = checkout_entry(ce, state, NULL);
+       status = checkout_entry(ce, state, NULL, nr_checkouts);
        discard_cache_entry(ce);
        return status;
 }
@@ -257,6 +259,7 @@ static int checkout_paths(const struct checkout_opts *opts,
        struct commit *head;
        int errs = 0;
        struct lock_file lock_file = LOCK_INIT;
+       int nr_checkouts = 0;
 
        if (opts->track != BRANCH_TRACK_UNSPECIFIED)
                die(_("'%s' cannot be used with updating paths"), "--track");
@@ -371,17 +374,36 @@ static int checkout_paths(const struct checkout_opts *opts,
                struct cache_entry *ce = active_cache[pos];
                if (ce->ce_flags & CE_MATCHED) {
                        if (!ce_stage(ce)) {
-                               errs |= checkout_entry(ce, &state, NULL);
+                               errs |= checkout_entry(ce, &state,
+                                                      NULL, &nr_checkouts);
                                continue;
                        }
                        if (opts->writeout_stage)
-                               errs |= checkout_stage(opts->writeout_stage, ce, pos, &state);
+                               errs |= checkout_stage(opts->writeout_stage,
+                                                      ce, pos,
+                                                      &state, &nr_checkouts);
                        else if (opts->merge)
-                               errs |= checkout_merged(pos, &state);
+                               errs |= checkout_merged(pos, &state,
+                                                       &nr_checkouts);
                        pos = skip_same_name(ce, pos) - 1;
                }
        }
-       errs |= finish_delayed_checkout(&state);
+       errs |= finish_delayed_checkout(&state, &nr_checkouts);
+
+       if (opts->count_checkout_paths) {
+               if (opts->source_tree)
+                       fprintf_ln(stderr, Q_("Checked out %d path out of %s",
+                                             "Checked out %d paths out of %s",
+                                             nr_checkouts),
+                                  nr_checkouts,
+                                  find_unique_abbrev(&opts->source_tree->object.oid,
+                                                     DEFAULT_ABBREV));
+               else
+                       fprintf_ln(stderr, Q_("Checked out %d path out of the index",
+                                             "Checked out %d paths out of the index",
+                                             nr_checkouts),
+                                  nr_checkouts);
+       }
 
        if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
                die(_("unable to write new index file"));
@@ -1064,6 +1086,7 @@ static int parse_branchname_arg(int argc, const char **argv,
                has_dash_dash = 1; /* case (3) or (1) */
        else if (dash_dash_pos >= 2)
                die(_("only one reference expected, %d given."), dash_dash_pos);
+       opts->count_checkout_paths = !opts->quiet && !has_dash_dash;
 
        if (!strcmp(arg, "-"))
                arg = "@{-1}";
index 544b0e86397cb98ddfdad3cffdd983905ee36029..71318c26e177e8aa4176201e4f23e6f43b63b630 100644 (file)
@@ -323,7 +323,7 @@ static int checkout_path(unsigned mode, struct object_id *oid,
        int ret;
 
        ce = make_transient_cache_entry(mode, oid, path, 0);
-       ret = checkout_entry(ce, state, NULL);
+       ret = checkout_entry(ce, state, NULL, NULL);
 
        discard_cache_entry(ce);
        return ret;
diff --git a/cache.h b/cache.h
index ca36b44ee0b5851f837616c322a201ac420a90d2..49713cc5a5a61bf0749e596b94474f00286dc652 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1539,9 +1539,9 @@ struct checkout {
 #define CHECKOUT_INIT { NULL, "" }
 
 #define TEMPORARY_FILENAME_LENGTH 25
-extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
+extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath, int *nr_checkouts);
 extern void enable_delayed_checkout(struct checkout *state);
-extern int finish_delayed_checkout(struct checkout *state);
+extern int finish_delayed_checkout(struct checkout *state, int *nr_checkouts);
 
 struct cache_def {
        struct strbuf path;
diff --git a/entry.c b/entry.c
index 5d136c5d55e0811b70fdb10f59ea506ceb1b273b..5f213c30fe8c099a25492beca8b074919d7fbfe1 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -161,7 +161,7 @@ static int remove_available_paths(struct string_list_item *item, void *cb_data)
        return !available;
 }
 
-int finish_delayed_checkout(struct checkout *state)
+int finish_delayed_checkout(struct checkout *state, int *nr_checkouts)
 {
        int errs = 0;
        unsigned delayed_object_count;
@@ -226,7 +226,7 @@ int finish_delayed_checkout(struct checkout *state)
                                ce = index_file_exists(state->istate, path->string,
                                                       strlen(path->string), 0);
                                if (ce) {
-                                       errs |= checkout_entry(ce, state, NULL);
+                                       errs |= checkout_entry(ce, state, NULL, nr_checkouts);
                                        filtered_bytes += ce->ce_stat_data.sd_size;
                                        display_throughput(progress, filtered_bytes);
                                } else
@@ -435,8 +435,8 @@ static void mark_colliding_entries(const struct checkout *state,
  * its name is returned in topath[], which must be able to hold at
  * least TEMPORARY_FILENAME_LENGTH bytes long.
  */
-int checkout_entry(struct cache_entry *ce,
-                  const struct checkout *state, char *topath)
+int checkout_entry(struct cache_entry *ce, const struct checkout *state,
+                  char *topath, int *nr_checkouts)
 {
        static struct strbuf path = STRBUF_INIT;
        struct stat st;
@@ -506,5 +506,7 @@ int checkout_entry(struct cache_entry *ce,
                return 0;
 
        create_directories(path.buf, path.len, state);
+       if (nr_checkouts)
+               (*nr_checkouts)++;
        return write_entry(ce, path.buf, state, 0);
 }
index 7570df481bf69824e4b163a6c7a15985b72d1326..17f1e601da5b344a6ed12c9fc3a7e449d745cb5e 100644 (file)
@@ -294,7 +294,7 @@ static void load_gitmodules_file(struct index_state *index,
                        repo_read_gitmodules(the_repository);
                } else if (state && (ce->ce_flags & CE_UPDATE)) {
                        submodule_free(the_repository);
-                       checkout_entry(ce, state, NULL);
+                       checkout_entry(ce, state, NULL, NULL);
                        repo_read_gitmodules(the_repository);
                }
        }
@@ -450,12 +450,12 @@ static int check_updates(struct unpack_trees_options *o)
                        display_progress(progress, ++cnt);
                        ce->ce_flags &= ~CE_UPDATE;
                        if (o->update && !o->dry_run) {
-                               errs |= checkout_entry(ce, &state, NULL);
+                               errs |= checkout_entry(ce, &state, NULL, NULL);
                        }
                }
        }
        stop_progress(&progress);
-       errs |= finish_delayed_checkout(&state);
+       errs |= finish_delayed_checkout(&state, NULL);
        if (o->update)
                git_attr_set_direction(GIT_ATTR_CHECKIN);