Merge branch 'jc/maint-checkout-keep-remove'
authorJunio C Hamano <gitster@pobox.com>
Tue, 16 Sep 2008 07:49:59 +0000 (00:49 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 Sep 2008 07:49:59 +0000 (00:49 -0700)
* jc/maint-checkout-keep-remove:
checkout: do not lose staged removal

1  2 
builtin-checkout.c
diff --combined builtin-checkout.c
index d986ac7abbd619c486a377e4433cf3fca687ea7a,774f29992a967201d1d4f39e6d2a9993d11a8eb7..9377a1c71ea8571d3e36e9e19aa322db765e93c8
@@@ -76,15 -76,6 +76,15 @@@ static int read_tree_some(struct tree *
        return 0;
  }
  
 +static int skip_same_name(struct cache_entry *ce, int pos)
 +{
 +      while (++pos < active_nr &&
 +             !strcmp(active_cache[pos]->name, ce->name))
 +              ; /* skip */
 +      return pos;
 +}
 +
 +
  static int checkout_paths(struct tree *source_tree, const char **pathspec)
  {
        int pos;
        if (report_path_error(ps_matched, pathspec, 0))
                return 1;
  
 +      /* Any unmerged paths? */
 +      for (pos = 0; pos < active_nr; pos++) {
 +              struct cache_entry *ce = active_cache[pos];
 +              if (pathspec_match(pathspec, NULL, ce->name, 0)) {
 +                      if (!ce_stage(ce))
 +                              continue;
 +                      errs = 1;
 +                      error("path '%s' is unmerged", ce->name);
 +                      pos = skip_same_name(ce, pos) - 1;
 +              }
 +      }
 +      if (errs)
 +              return 1;
 +
        /* Now we are committed to check them out */
        memset(&state, 0, sizeof(state));
        state.force = 1;
        for (pos = 0; pos < active_nr; pos++) {
                struct cache_entry *ce = active_cache[pos];
                if (pathspec_match(pathspec, NULL, ce->name, 0)) {
 -                      errs |= checkout_entry(ce, &state, NULL);
 +                      if (!ce_stage(ce)) {
 +                              errs |= checkout_entry(ce, &state, NULL);
 +                              continue;
 +                      }
 +                      pos = skip_same_name(ce, pos) - 1;
                }
        }
  
@@@ -184,7 -157,7 +184,7 @@@ struct checkout_opts 
        int force;
        int writeout_error;
  
 -      char *new_branch;
 +      const char *new_branch;
        int new_branch_log;
        enum branch_track track;
  };
@@@ -269,6 -242,8 +269,8 @@@ static int merge_working_tree(struct ch
                }
  
                /* 2-way merge to the new branch */
+               topts.initial_checkout = (!active_nr &&
+                                         (old->commit == new->commit));
                topts.update = 1;
                topts.merge = 1;
                topts.gently = opts->merge;
@@@ -462,28 -437,13 +464,28 @@@ int cmd_checkout(int argc, const char *
  
        git_config(git_default_config, NULL);
  
 -      opts.track = git_branch_track;
 +      opts.track = BRANCH_TRACK_UNSPECIFIED;
  
        argc = parse_options(argc, argv, options, checkout_usage,
                             PARSE_OPT_KEEP_DASHDASH);
  
 -      if (!opts.new_branch && (opts.track != git_branch_track))
 -              die("git checkout: --track and --no-track require -b");
 +      /* --track without -b should DWIM */
 +      if (0 < opts.track && !opts.new_branch) {
 +              const char *argv0 = argv[0];
 +              if (!argc || !strcmp(argv0, "--"))
 +                      die ("--track needs a branch name");
 +              if (!prefixcmp(argv0, "refs/"))
 +                      argv0 += 5;
 +              if (!prefixcmp(argv0, "remotes/"))
 +                      argv0 += 8;
 +              argv0 = strchr(argv0, '/');
 +              if (!argv0 || !argv0[1])
 +                      die ("Missing branch name; try -b");
 +              opts.new_branch = argv0 + 1;
 +      }
 +
 +      if (opts.track == BRANCH_TRACK_UNSPECIFIED)
 +              opts.track = git_branch_track;
  
        if (opts.force && opts.merge)
                die("git checkout: -f and -m are incompatible");