X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=topgit.git;a=blobdiff_plain;f=tg-create.sh;h=6ee3f027d23e797ac80e07c1024b22aaedc461f5;hp=0db1cf376bdde093396a96cfd8df0eec8a96fd00;hb=a5dbc6a4a9e01c4e3b21b4c882acfd479c703a40;hpb=ab712f2ed92a6e451bf2d482b03d2559697bf100 diff --git a/tg-create.sh b/tg-create.sh index 0db1cf3..6ee3f02 100644 --- a/tg-create.sh +++ b/tg-create.sh @@ -7,6 +7,7 @@ deps= # List of dependent branches restarted= # Set to 1 if we are picking up in the middle of base setup merge= # List of branches to be merged; subset of $deps name= +rname= # Remote branch to base this one on ## Parse options @@ -14,8 +15,10 @@ name= while [ -n "$1" ]; do arg="$1"; shift case "$arg" in + -r) + rname="$1"; shift;; -*) - echo "Usage: tg create [-d DEPS...] NAME" >&2 + echo "Usage: tg [...] create NAME [DEPS...|-r RNAME]" >&2 exit 1;; *) if [ -z "$name" ]; then @@ -27,22 +30,35 @@ while [ -n "$1" ]; do done +## Fast-track creating branches based on remote ones + +if [ -n "$rname" ]; then + [ -n "$name" ] || die "no branch name given" + ! ref_exists "$name" || die "branch '$name' already exists" + has_remote "$rname" || die "no branch $rname in remote $base_remote" + + git update-ref "refs/top-bases/$name" "refs/remotes/$base_remote/top-bases/$rname" + git update-ref "refs/heads/$name" "refs/remotes/$base_remote/$rname" + info "Topic branch $name based on $base_remote : $rname set up." + exit 0 +fi + + ## Auto-guess dependencies deps="${deps# }" if [ -z "$deps" ]; then - head="$(git symbolic-ref HEAD)" - bname="${head#refs/top-bases/}" - if [ "$bname" != "$head" -a -s "$git_dir/top-deps" -a -s "$git_dir/top-merge" ]; then - # We are on a base branch now; resume merge! + if [ -z "$name" -a -s "$git_dir/top-name" -a -s "$git_dir/top-deps" -a -s "$git_dir/top-merge" ]; then + # We are setting up the base branch now; resume merge! + name="$(cat "$git_dir/top-name")" deps="$(cat "$git_dir/top-deps")" merge="$(cat "$git_dir/top-merge")" - name="$bname" restarted=1 info "Resuming $name setup..." else # The common case [ -z "$name" ] && die "no branch name given" + head="$(git symbolic-ref HEAD)" deps="${head#refs/heads/}" [ "$deps" != "$head" ] || die "refusing to auto-depend on non-head ref ($head)" info "Automatically marking dependency on $deps" @@ -52,14 +68,14 @@ fi [ -n "$merge" -o -n "$restarted" ] || merge="$deps " for d in $deps; do - git rev-parse --verify "$d" >/dev/null 2>&1 || + ref_exists "$d" || die "unknown branch dependency '$d'" done -! git rev-parse --verify "$name" >/dev/null 2>&1 || +! ref_exists "$name" || die "branch '$name' already exists" # Clean up any stale stuff -rm -f "$git_dir/top-deps" "$git_dir/top-merge" +rm -f "$git_dir/top-name" "$git_dir/top-deps" "$git_dir/top-merge" ## Create base @@ -69,7 +85,8 @@ if [ -n "$merge" ]; then branch="${merge%% *}" merge="${merge#* }" info "Creating $name base from $branch..." - switch_to_base "$name" "$branch" + # We create a detached head so that we can abort this operation + git checkout -q "$(git rev-parse "$branch")" fi @@ -82,10 +99,11 @@ while [ -n "$merge" ]; do info "Merging $name base with $branch..." if ! git merge "$branch"; then - info "Please commit merge resolution and call: tg create" - info "It is also safe to abort this operation using \`git reset --hard\`" - info "but please remember you are on the base branch now;" - info "you will want to switch to a different branch." + info "Please commit merge resolution and call: $tg create" + info "It is also safe to abort this operation using:" + info "git reset --hard some_branch" + info "(You are on a detached HEAD now.)" + echo "$name" >"$git_dir/top-name" echo "$deps" >"$git_dir/top-deps" echo "$merge" >"$git_dir/top-merge" exit 2 @@ -95,16 +113,21 @@ done ## Set up the topic branch +git update-ref "refs/top-bases/$name" "HEAD" "" git checkout -b "$name" echo "$deps" | sed 's/ /\n/g' >"$root_dir/.topdeps" -git add "$root_dir/.topdeps" +git add -f "$root_dir/.topdeps" author="$(git var GIT_AUTHOR_IDENT)" author_addr="${author%> *}>" { echo "From: $author_addr" - echo "Subject: [PATCH] $1" + ! header="$(git config topgit.to)" || echo "To: $header" + ! header="$(git config topgit.cc)" || echo "Cc: $header" + ! header="$(git config topgit.bcc)" || echo "Bcc: $header" + ! subject_prefix="$(git config topgit.subjectprefix)" || subject_prefix="$subject_prefix " + echo "Subject: [${subject_prefix}PATCH] $name" echo cat < @@ -112,9 +135,9 @@ author_addr="${author%> *}>" Signed-off-by: $author_addr EOT } >"$root_dir/.topmsg" -git add "$root_dir/.topmsg" +git add -f "$root_dir/.topmsg" info "Topic branch $name set up. Please fill .topmsg now and make initial commit." -info "To abort: git rm -f .top* && git checkout ${deps%% *} && tg delete $name" +info "To abort: git rm -f .top* && git checkout ${deps%% *} && $tg delete $name"