3 #=======================================================================
5 # File ID: ee782996-282c-11e2-9c05-00c0a8deee11
7 # Push to all predefined Git remotes in one go.
10 # ©opyleft 2012– Øyvind A. Holm <sunny@sunbase.org>
11 # License: GNU General Public License version 2 or later, see end of
12 # file for legal stuff.
13 #=======================================================================
23 'regexpfile' => "$ENV{'HOME'}/.git-pa-remotes",
33 'regexpfile' => $Std{'regexpfile'},
41 $progname =~ s/^.*\/(.*?)$/$1/;
42 our $VERSION = '0.6.0';
44 Getopt
::Long
::Configure
('bundling');
47 'all-remotes|a' => \
$Opt{'all-remotes'},
48 'dry-run|n' => \
$Opt{'dry-run'},
49 'force|f' => \
$Opt{'force'},
50 'help|h' => \
$Opt{'help'},
51 'quiet|q+' => \
$Opt{'quiet'},
52 'regexpfile=s' => \
$Opt{'regexpfile'},
53 'synced-only|s' => \
$Opt{'synced-only'},
54 'verbose|v+' => \
$Opt{'verbose'},
55 'version' => \
$Opt{'version'},
57 ) || die("$progname: Option error. Use -h for help.\n");
59 $Opt{'verbose'} -= $Opt{'quiet'};
60 $Opt{'help'} && usage
(0);
61 if ($Opt{'version'}) {
72 $Opt{'dry-run'} && msg
(0, "Note: This is just a simulation.");
74 if ($Opt{'synced-only'}) {
82 For every regexp in ~/.git-pa-remotes
83 List remotes | grep ^remote | grep current regexp
85 If the remote is specified in git-pa.allremotes
91 my @pushremotes = read_regexpfile
($Opt{'regexpfile'});
93 my @cmdline_args = @ARGV;
94 msg
(2, "cmdline_args = '" . join('|', @cmdline_args) . "'");
96 my $config_allremotes = `git config --get git-pa.allremotes`;
97 chomp($config_allremotes);
98 my @allremotes_elem = split(' ', $config_allremotes);
99 msg
(1, 'Will use --all and --tags with the following remotes: ' .
100 join(', ', @allremotes_elem));
103 for (@allremotes_elem) {
107 for my $f (`git remote`) {
110 for my $ch (@pushremotes) {
112 msg
(4, "ch = '$ch'");
114 open($pipefp, 'git remote -v |') or
115 die("$progname: git remote -v: Cannot open pipe: $!\n");
116 while (my $curr = <$pipefp>) {
118 msg
(5, "curr = '$curr'");
119 if ($curr =~ /^$f\s/ && $curr =~ /$ch/) {
120 msg
(2, "Found ('$curr' =~ /$ch/)");
126 $Opt{'all-remotes'} && ($do_push = 1);
131 open($pipefp, 'git tag |') or
132 die("$progname: git tag: Cannot open pipe: $!\n");
133 my $check_tag = <$pipefp>;
134 $tags_found = 1 if (defined($check_tag));
136 msg
(2, "tags_found = \"$tags_found\"");
139 mysystem
('git', 'push', '--force', $f, @ARGV);
141 mysystem
('git', 'push', $f, @ARGV);
143 if (defined($allremotes{$f})) {
144 mysystem
('git', 'push', '--all', $f);
145 mysystem
('git', 'push', '--tags', $f) if ($tags_found);
157 my $local_branches = `git branch | cut -c 3-`;
159 open($pipefp, "git branch | cut -c 3-|");
160 while (my $curr = <$pipefp>) {
162 next if ($curr =~ /^synced\//);
163 if ($local_branches =~ /^synced\/$curr$/m
) {
165 mysystem
("git", "push", "-f", ".", "$curr:synced/$curr");
167 mysystem
("git", "push", ".", "$curr:synced/$curr");
169 system("git", "branch", "-q", "-u", "synced/$curr", $curr);
182 die("\n$progname: Child process interrupted, aborting.\n");
191 msg
(0, "Executing '" . join(' ', @args) . "'");
192 $Opt{'dry-run'} || system(@args) && check_sig
($?
);
197 sub read_regexpfile
{
199 my $regexpfile = shift;
202 open($fp, '<', $regexpfile) ||
203 die("$progname: $regexpfile: Could not read regexp file: $!\n");
204 while (my $curr = <$fp>) {
206 push(@Retval, $curr);
207 msg
(3, "regexp: $curr");
211 } # read_regexpfile()
214 # Print program version {{{
215 print("$progname $VERSION\n");
221 # Send the help message to stdout {{{
224 if ($Opt{'verbose'}) {
230 Push to all predefined Git remotes in one go. If any synced/* branches
231 exist, push the parent branch to them to get them in sync. Also set all
232 branches with a corresponding synced/ branch up to track the synced/
233 branch. This will show up in a Git-aware prompt that new commits have
234 been pushed to the local branch, or there are commits that haven't been
237 Usage: $progname [options] [args for git push]
242 Push to all local remotes.
244 Use --force when pushing. Overwrites remote branches, be careful.
248 Don't really push the branches, simulate only.
250 Be more quiet. Can be repeated to increase silence.
252 Use regexpfile X instead of the default
253 '$Std{'regexpfile'}'.
255 Don't push, only update the local synced/* branches.
257 Increase level of verbosity. Can be repeated.
259 Print version information.
261 The 'git-pa.allremotes' configuration option can contain a
262 space-separated list of remotes which will also get pushed to using
263 '--all' and '--tags'.
271 # Print a status message to stderr based on verbosity level {{{
272 my ($verbose_level, $Txt) = @_;
274 if ($Opt{'verbose'} >= $verbose_level) {
275 print(STDERR
"$progname: $Txt\n");
283 # This program is free software; you can redistribute it and/or modify
284 # it under the terms of the GNU General Public License as published by
285 # the Free Software Foundation; either version 2 of the License, or (at
286 # your option) any later version.
288 # This program is distributed in the hope that it will be useful, but
289 # WITHOUT ANY WARRANTY; without even the implied warranty of
290 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
291 # See the GNU General Public License for more details.
293 # You should have received a copy of the GNU General Public License
294 # along with this program.
295 # If not, see L<http://www.gnu.org/licenses/>.
297 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :