Skip to content

Commit

Permalink
Merge branch 'db/checkout'
Browse files Browse the repository at this point in the history
* db/checkout: (21 commits)
  checkout: error out when index is unmerged even with -m
  checkout: show progress when checkout takes long time while switching branches
  Add merge-subtree back
  checkout: updates to tracking report
  builtin-checkout.c: Remove unused prefix arguments in switch_branches path
  checkout: work from a subdirectory
  checkout: tone down the "forked status" diagnostic messages
  Clean up reporting differences on branch switch
  builtin-checkout.c: fix possible usage segfault
  checkout: notice when the switched branch is behind or forked
  Build in checkout
  Move code to clean up after a branch change to branch.c
  Library function to check for unmerged index entries
  Use diff -u instead of diff in t7201
  Move create_branch into a library file
  Build-in merge-recursive
  Add "skip_unmerged" option to unpack_trees.
  Discard "deleted" cache entries after using them to update the working tree
  Send unpack-trees debugging output to stderr
  Add flag to make unpack_trees() not print errors.
  ...

Conflicts:

	Makefile
  • Loading branch information
gitster committed Feb 27, 2008
2 parents 992221d + 04c9e11 commit 5a4d707
Show file tree
Hide file tree
Showing 20 changed files with 1,002 additions and 271 deletions.
15 changes: 7 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ BASIC_CFLAGS =
BASIC_LDFLAGS =

SCRIPT_SH = \
git-bisect.sh git-checkout.sh \
git-bisect.sh \
git-clone.sh \
git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \
git-pull.sh git-rebase.sh git-rebase--interactive.sh \
Expand Down Expand Up @@ -265,23 +265,23 @@ PROGRAMS = \
git-upload-pack$X \
git-pack-redundant$X git-var$X \
git-merge-tree$X git-imap-send$X \
git-merge-recursive$X \
$(EXTRA_PROGRAMS)

# Empty...
EXTRA_PROGRAMS =

# List built-in command $C whose implementation cmd_$C() is not in
# builtin-$C.o but is linked in as part of some other command.
BUILT_INS = \
git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \
git-get-tar-commit-id$X git-init$X git-repo-config$X \
git-fsck-objects$X git-cherry-pick$X git-peek-remote$X git-status$X \
git-merge-subtree$X \
$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))

# what 'all' will build and 'install' will install, in gitexecdir
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)

ALL_PROGRAMS += git-merge-subtree$X

# what 'all' will build but not install in gitexecdir
OTHER_PROGRAMS = git$X gitweb/gitweb.cgi

Expand Down Expand Up @@ -327,7 +327,7 @@ LIB_OBJS = \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
transport.o bundle.o walker.o parse-options.o ws.o archive.o \
transport.o bundle.o walker.o parse-options.o ws.o archive.o branch.o \
alias.o

BUILTIN_OBJS = \
Expand All @@ -340,6 +340,7 @@ BUILTIN_OBJS = \
builtin-bundle.o \
builtin-cat-file.o \
builtin-check-attr.o \
builtin-checkout.o \
builtin-checkout-index.o \
builtin-check-ref-format.o \
builtin-clean.o \
Expand Down Expand Up @@ -370,6 +371,7 @@ BUILTIN_OBJS = \
builtin-merge-base.o \
builtin-merge-file.o \
builtin-merge-ours.o \
builtin-merge-recursive.o \
builtin-mv.o \
builtin-name-rev.o \
builtin-pack-objects.o \
Expand Down Expand Up @@ -840,9 +842,6 @@ help.o: help.c common-cmds.h GIT-CFLAGS
'-DGIT_MAN_PATH="$(mandir_SQ)"' \
'-DGIT_INFO_PATH="$(infodir_SQ)"' $<

git-merge-subtree$X: git-merge-recursive$X
$(QUIET_BUILT_IN)$(RM) $@ && ln git-merge-recursive$X $@

$(BUILT_INS): git$X
$(QUIET_BUILT_IN)$(RM) $@ && ln git$X $@

Expand Down
148 changes: 148 additions & 0 deletions branch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#include "cache.h"
#include "branch.h"
#include "refs.h"
#include "remote.h"
#include "commit.h"

struct tracking {
struct refspec spec;
char *src;
const char *remote;
int matches;
};

static int find_tracked_branch(struct remote *remote, void *priv)
{
struct tracking *tracking = priv;

if (!remote_find_tracking(remote, &tracking->spec)) {
if (++tracking->matches == 1) {
tracking->src = tracking->spec.src;
tracking->remote = remote->name;
} else {
free(tracking->spec.src);
if (tracking->src) {
free(tracking->src);
tracking->src = NULL;
}
}
tracking->spec.src = NULL;
}

return 0;
}

/*
* This is called when new_ref is branched off of orig_ref, and tries
* to infer the settings for branch.<new_ref>.{remote,merge} from the
* config.
*/
static int setup_tracking(const char *new_ref, const char *orig_ref)
{
char key[1024];
struct tracking tracking;

if (strlen(new_ref) > 1024 - 7 - 7 - 1)
return error("Tracking not set up: name too long: %s",
new_ref);

memset(&tracking, 0, sizeof(tracking));
tracking.spec.dst = (char *)orig_ref;
if (for_each_remote(find_tracked_branch, &tracking) ||
!tracking.matches)
return 1;

if (tracking.matches > 1)
return error("Not tracking: ambiguous information for ref %s",
orig_ref);

if (tracking.matches == 1) {
sprintf(key, "branch.%s.remote", new_ref);
git_config_set(key, tracking.remote ? tracking.remote : ".");
sprintf(key, "branch.%s.merge", new_ref);
git_config_set(key, tracking.src);
free(tracking.src);
printf("Branch %s set up to track remote branch %s.\n",
new_ref, orig_ref);
}

return 0;
}

void create_branch(const char *head,
const char *name, const char *start_name,
int force, int reflog, int track)
{
struct ref_lock *lock;
struct commit *commit;
unsigned char sha1[20];
char *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20];
int forcing = 0;

snprintf(ref, sizeof ref, "refs/heads/%s", name);
if (check_ref_format(ref))
die("'%s' is not a valid branch name.", name);

if (resolve_ref(ref, sha1, 1, NULL)) {
if (!force)
die("A branch named '%s' already exists.", name);
else if (!is_bare_repository() && !strcmp(head, name))
die("Cannot force update the current branch.");
forcing = 1;
}

real_ref = NULL;
if (get_sha1(start_name, sha1))
die("Not a valid object name: '%s'.", start_name);

switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
case 0:
/* Not branching from any existing branch */
real_ref = NULL;
break;
case 1:
/* Unique completion -- good */
break;
default:
die("Ambiguous object name: '%s'.", start_name);
break;
}

if ((commit = lookup_commit_reference(sha1)) == NULL)
die("Not a valid branch point: '%s'.", start_name);
hashcpy(sha1, commit->object.sha1);

lock = lock_any_ref_for_update(ref, NULL, 0);
if (!lock)
die("Failed to lock ref for update: %s.", strerror(errno));

if (reflog)
log_all_ref_updates = 1;

if (forcing)
snprintf(msg, sizeof msg, "branch: Reset from %s",
start_name);
else
snprintf(msg, sizeof msg, "branch: Created from %s",
start_name);

/* When branching off a remote branch, set up so that git-pull
automatically merges from there. So far, this is only done for
remotes registered via .git/config. */
if (real_ref && track)
setup_tracking(name, real_ref);

if (write_ref_sha1(lock, sha1, msg) < 0)
die("Failed to write ref: %s.", strerror(errno));

if (real_ref)
free(real_ref);
}

void remove_branch_state(void)
{
unlink(git_path("MERGE_HEAD"));
unlink(git_path("rr-cache/MERGE_RR"));
unlink(git_path("MERGE_MSG"));
unlink(git_path("SQUASH_MSG"));
}
24 changes: 24 additions & 0 deletions branch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef BRANCH_H
#define BRANCH_H

/* Functions for acting on the information about branches. */

/*
* Creates a new branch, where head is the branch currently checked
* out, name is the new branch name, start_name is the name of the
* existing branch that the new branch should start from, force
* enables overwriting an existing (non-head) branch, reflog creates a
* reflog for the branch, and track causes the new branch to be
* configured to merge the remote branch that start_name is a tracking
* branch for (if any).
*/
void create_branch(const char *head, const char *name, const char *start_name,
int force, int reflog, int track);

/*
* Remove information about the state of working on the current
* branch. (E.g., MERGE_HEAD)
*/
void remove_branch_state(void);

#endif
Loading

0 comments on commit 5a4d707

Please sign in to comment.