summaryrefslogtreecommitdiff
path: root/bin/git-push-all
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2020-03-23 22:14:59 -0700
committerSean Whitton <spwhitton@spwhitton.name>2020-03-23 22:15:44 -0700
commit05add5a36aa5208ffa289540a039621806949c91 (patch)
treedae51a5b76fff7eca30432a6f39514478b29cb36 /bin/git-push-all
parent3b02f5e5a24cee5a4a48b03e81bbe02541b86958 (diff)
downloaddotfiles-05add5a36aa5208ffa289540a039621806949c91.tar.gz
rewrite git-push-all
Diffstat (limited to 'bin/git-push-all')
-rwxr-xr-xbin/git-push-all102
1 files changed, 47 insertions, 55 deletions
diff --git a/bin/git-push-all b/bin/git-push-all
index df3f5af3..553f4f03 100755
--- a/bin/git-push-all
+++ b/bin/git-push-all
@@ -2,7 +2,7 @@
# git-push-all -- intelligently push most branches
-# Copyright (C) 2016, 2019 Sean Whitton
+# Copyright (C) 2016, 2019, 2020 Sean Whitton
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,15 +17,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-# Prerequisites:
-
-# The Git::Wrapper, Array::Utils, Config::GitLike, and List::MoreUtils
-# perl libraries. On a Debian system,
-# apt-get install libgit-wrapper-perl libconfig-gitlike-perl \
-# liblist-moreutils-perl libarray-utils-perl
-
-# Description:
-
# This script will try to push all your branches to the places they
# should be pushed, with --follow-tags. Specifically, for each branch,
#
@@ -40,65 +31,69 @@
# If a branch is tracking a remote that you cannot push to, be sure to
# set at least one of branch.pushRemote and remote.pushDefault.
-# TODO --confirm to show what will be pushed to where and ask for confirmation 'branch -> remote#target'
+# Enhancement: --confirm to show what will be pushed to where, and ask
+# for confirmation: 'branch -> remote#target'
+use 5.028;
use strict;
use warnings;
use lib "$ENV{HOME}/src/dotfiles/perl5";
-no warnings "experimental::smartmatch";
use Cwd;
-use Array::Utils qw{ array_minus };
use Git::Wrapper;
-use Config::GitLike;
-use List::MoreUtils qw{ apply };
use Local::Util::Git qw(unpushed_tags);
my $git = Git::Wrapper->new(getcwd);
-my $config = Config::GitLike->new( confname => 'config' );
-$config->load_file('.git/config');
-
-my @branches = apply { s/[ \*]//g } $git->branch;
-my @allBranches = apply { s/[ \*]//g } $git->branch({ all => 1 });
-my $pushDefault = $config->get( key => "remote.pushDefault" );
+my @local_branches
+ = $git->for_each_ref({ format => '%(refname)' }, "refs/heads");
+my %remote_branches = map +($_ => undef),
+ $git->for_each_ref({ format => '%(refname)' }, "refs/remotes");
+my ($pushDefault)
+ = $git->config(qw|--local --get --default|, "", "remote.pushDefault");
my %pushes;
-foreach my $branch ( @branches ) {
- my $pushRemote = $config->get( key => "branch.$branch.pushRemote" );
- my $tracking = $config->get( key => "branch.$branch.remote" );
-
- if ( defined $pushRemote ) {
- # print "I: pushing $branch to $pushRemote (its pushRemote)\n";
- push @{ $pushes{$pushRemote} }, $branch;
- # don't push unless it already exists on the remote: this script
- # avoids creating branches
- } elsif ( defined $pushDefault
- && "remotes/$pushDefault/$branch" ~~ @allBranches ) {
- # print "I: pushing $branch to $pushDefault (the remote.pushDefault)\n";
- push @{ $pushes{$pushDefault} }, $branch;
- } elsif ( !defined $pushDefault && defined $tracking
- && "remotes/$tracking/$branch" ~~ @allBranches ) {
- # print "I: pushing $branch to $tracking (probably to its tracking branch)\n";
- push @{ $pushes{$tracking} }, $branch;
+foreach my $branch (@local_branches) {
+ (my $short_branch = $branch) =~ s#^refs/heads/##;
+ my ($pushRemote) = $git->config(qw|--local --get --default|,
+ "", "branch.$short_branch.pushRemote");
+ my ($tracking)
+ = $git->for_each_ref({ format => "%(upstream)" }, $branch);
+ my ($tracking_remote) = $tracking =~ m#refs/remotes/([^/]+)/# if $tracking;
+
+ # note that except in the case of a defined pushRemote we don't
+ # push unless the branch already exists on the remote: this script
+ # avoids creating new branches
+ if ($pushRemote) {
+ # say "I: pushing $short_branch to $pushRemote (its pushRemote)";
+ push $pushes{$pushRemote}->@*, $branch;
+ } elsif ($pushDefault
+ and exists $remote_branches{"refs/remotes/$pushDefault/$short_branch"})
+ {
+ # say "I: pushing $short_branch to $pushDefault (the remote.pushDefault)";
+ push $pushes{$pushDefault}->@*, $branch;
+ } elsif (!$pushDefault
+ and $tracking
+ and exists $remote_branches{$tracking}) {
+ # say "I: pushing $short_branch to its tracking branch, $tracking";
+ push $pushes{$tracking_remote}->@*, $branch;
} else {
- print "E: couldn't find anywhere to push $branch\n";
- print "I: maybe you want to \`git branchmove\` it to a remote\n";
+ say "E: couldn't find anywhere to push $branch";
+ say "I: maybe you want to \`git branchmove\` it to a remote\n";
exit 1;
}
}
-foreach my $remote ( keys %pushes ) {
+foreach my $remote (keys %pushes) {
# TODO if $remote eq $pushDefault, consider s/follow-// below (and
# pushRemote of master branch, if that exists?)
# I almost certainly want all tags on that remote (e.g. an alioth repo)
- my @branches = @{ $pushes{$remote} };
- if ( "--no-verify" ~~ @ARGV ) {
- system "git push --follow-tags --no-verify $remote @branches";
- } else {
- system "git push --follow-tags $remote @branches";
- }
- exit 1 if ( $? != 0 );
+ my @branches = $pushes{$remote}->@*;
+ my @args = qw(--follow-tags);
+ push @args, "--no-verify" if grep $_ eq "--no-verify", @ARGV;
+
+ # bypass Git::Wrapper which can hang pushing to salsa
+ system "git", "push", @args, $remote, @branches;
}
# Now find any tags that have not been pushed to any remote.
@@ -112,13 +107,10 @@ foreach my $remote ( keys %pushes ) {
# TODO definitely split out because should be run as a safety catch by
# src-unregistered
-unless ( "--no-tags" ~~ @ARGV ) {
- my @unpushed_tags = unpushed_tags();
-
- if ( scalar @unpushed_tags > 0 ) {
- print "E: the following tags have not been pushed to any remote:\n";
- print join(", ", @unpushed_tags);
- print "\n";
+unless (grep $_ eq "--no-tags", @ARGV) {
+ if (my @unpushed_tags = unpushed_tags) {
+ say "E: the following tags have not been pushed to any remote:";
+ say join ", ", @unpushed_tags;
exit 1;
}
}