From 7ec5c5de02388e412e7bd8fe9ce937d9827e3bf9 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Fri, 3 May 2019 14:01:53 -0700 Subject: git-branchmove: code to attempt to detach the head --- bin/git-branchmove | 53 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) (limited to 'bin/git-branchmove') diff --git a/bin/git-branchmove b/bin/git-branchmove index fed28766..c59d936a 100755 --- a/bin/git-branchmove +++ b/bin/git-branchmove @@ -20,7 +20,7 @@ # This script is based on Ian Jackson's git-branchmove script, in the # chiark-utils Debian source package. Ian's script assumes throughout # that it is possible to have unrestricted shell access to the remote, -# however, while this script avoids that assumption. +# however, while this script avoids that global assumption. # # As much as possible we treat the remote argument as opaque, i.e., we # don't distinguish between git URIs and named remotes. That means @@ -94,6 +94,34 @@ die "git-branchmove: unknown operation\n" # is this a named remote or a git URL? my $named_remote = $remote =~ m|:| or $remote =~ m|^[/.]|; +# Attempt to determine how we might be able to run commands in the +# remote repo. This will only be used if we need to try to detach the +# remote HEAD. These regexps are lifted from Ian's script +my $rurl, my $rrune, my $rdir; +if ($named_remote) { + $rurl = `git remote get-url --push $remote`; +} else { + $rurl = $remote; +} +if ($rurl =~ m#^ssh://([^:/]+)(?:\:(\w+))?#) { + $rdir = "$'\''"; + $rrune = "ssh "; + if ($2) { + $rrune .= " -p $3"; + } + $rrune .= "$1"; +} elsif ($rurl =~ m#^([-+_.0-9a-zA-Z\@]+):(?!//|:)#) { + $rdir = "$'\''"; + $rrune = "ssh $1"; +} elsif ($rurl =~ m#^[/.]#) { + $rdir = $rurl; + $rrune = undef; +} + +# DEBUG +print "dir is $rdir and rune is $rrune\n"; +exit 0; + # If we don't prefix the patterns, we might match branches the user # doesn't intend. E.g. 'foo' would match 'wip/foo' my @branch_pats = map { $_ =~ s|^|[r]efs/heads/|; $_ } @patterns; @@ -134,9 +162,26 @@ if ($op eq "put") { $source_head = (split /\s/, $lines[0])[1]; } } -die "git-branchmove: would delete checked-out branch $source_head" - if (defined $source_head and - grep /^$source_head$/, map {$_->{ref}} @source_branches); +if (defined $source_head and + grep /^$source_head$/, map {$_->{ref}} @source_branches) { + if ($attempt_detach) { + if ($op eq 'put') { + $git->checkout('--detach'); + } elsif ($op eq 'get') { + if (defined $rrune and defined $rdir) { + system "$rrune \"set -e; cd $rdir; git checkout --detach\"" + or die "failed to detach remote HEAD"; + } elsif (!defined $rrune and defined $rdir) { + my $dest_git = Git::Wrapper->new($rdir); + $dest_git->checkout('--detach'); + } else { + die "git-branchmove: don't know how to detach remote HEAD"; + } + } + } else { + die "git-branchmove: would delete checked-out branch $source_head"; + } +} # check whether we would overwrite anything foreach my $source_branch (@source_branches) { -- cgit v1.2.3