summaryrefslogtreecommitdiff
path: root/builtin-branch.c
diff options
context:
space:
mode:
Diffstat (limited to 'builtin-branch.c')
-rw-r--r--builtin-branch.c55
1 files changed, 41 insertions, 14 deletions
diff --git a/builtin-branch.c b/builtin-branch.c
index d3df5a5..c760e18 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -275,7 +275,7 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
}
}
-static void print_ref_list(int kinds, int verbose, int abbrev)
+static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
{
int i;
struct ref_list ref_list;
@@ -286,8 +286,20 @@ static void print_ref_list(int kinds, int verbose, int abbrev)
qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
+ detached = (detached && (kinds & REF_LOCAL_BRANCH));
+ if (detached) {
+ struct ref_item item;
+ item.name = "(no branch)";
+ item.kind = REF_LOCAL_BRANCH;
+ hashcpy(item.sha1, head_sha1);
+ if (strlen(item.name) > ref_list.maxwidth)
+ ref_list.maxwidth = strlen(item.name);
+ print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1);
+ }
+
for (i = 0; i < ref_list.index; i++) {
- int current = (ref_list.list[i].kind == REF_LOCAL_BRANCH) &&
+ int current = !detached &&
+ (ref_list.list[i].kind == REF_LOCAL_BRANCH) &&
!strcmp(ref_list.list[i].name, head);
print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,
abbrev, current);
@@ -296,7 +308,8 @@ static void print_ref_list(int kinds, int verbose, int abbrev)
free_ref_list(&ref_list);
}
-static void create_branch(const char *name, const char *start,
+static void create_branch(const char *name, const char *start_name,
+ unsigned char *start_sha1,
int force, int reflog)
{
struct ref_lock *lock;
@@ -315,9 +328,14 @@ static void create_branch(const char *name, const char *start,
die("Cannot force update the current branch.");
}
- if (get_sha1(start, sha1) ||
- (commit = lookup_commit_reference(sha1)) == NULL)
- die("Not a valid branch point: '%s'.", start);
+ if (start_sha1)
+ /* detached HEAD */
+ hashcpy(sha1, start_sha1);
+ else if (get_sha1(start_name, sha1))
+ die("Not a valid object name: '%s'.", start_name);
+
+ 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);
@@ -326,7 +344,8 @@ static void create_branch(const char *name, const char *start,
if (reflog) {
log_all_ref_updates = 1;
- snprintf(msg, sizeof msg, "branch: Created from %s", start);
+ snprintf(msg, sizeof msg, "branch: Created from %s",
+ start_name);
}
if (write_ref_sha1(lock, sha1, msg) < 0)
@@ -338,6 +357,9 @@ static void rename_branch(const char *oldname, const char *newname, int force)
char oldref[PATH_MAX], newref[PATH_MAX], logmsg[PATH_MAX*2 + 100];
unsigned char sha1[20];
+ if (!oldname)
+ die("cannot rename the curren branch while not on any.");
+
if (snprintf(oldref, sizeof(oldref), "refs/heads/%s", oldname) > sizeof(oldref))
die("Old branchname too long");
@@ -367,7 +389,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
{
int delete = 0, force_delete = 0, force_create = 0;
int rename = 0, force_rename = 0;
- int verbose = 0, abbrev = DEFAULT_ABBREV;
+ int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
int reflog = 0;
int kinds = REF_LOCAL_BRANCH;
int i;
@@ -444,22 +466,27 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
head = xstrdup(resolve_ref("HEAD", head_sha1, 0, NULL));
if (!head)
die("Failed to resolve HEAD as a valid ref.");
- if (strncmp(head, "refs/heads/", 11))
- die("HEAD not found below refs/heads!");
- head += 11;
+ if (!strcmp(head, "HEAD")) {
+ detached = 1;
+ }
+ else {
+ if (strncmp(head, "refs/heads/", 11))
+ die("HEAD not found below refs/heads!");
+ head += 11;
+ }
if (delete)
return delete_branches(argc - i, argv + i, force_delete, kinds);
else if (i == argc)
- print_ref_list(kinds, verbose, abbrev);
+ print_ref_list(kinds, detached, verbose, abbrev);
else if (rename && (i == argc - 1))
rename_branch(head, argv[i], force_rename);
else if (rename && (i == argc - 2))
rename_branch(argv[i], argv[i + 1], force_rename);
else if (i == argc - 1)
- create_branch(argv[i], head, force_create, reflog);
+ create_branch(argv[i], head, head_sha1, force_create, reflog);
else if (i == argc - 2)
- create_branch(argv[i], argv[i + 1], force_create, reflog);
+ create_branch(argv[i], argv[i+1], NULL, force_create, reflog);
else
usage(builtin_branch_usage);