<p>Neels Hofmeyr <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/11560">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  osmith: Looks good to me, but someone else must approve; Verified
  Neels Hofmeyr: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">replace src/* git scripts with a single src/gits<br><br>I keep re-using this functionality in completely unrelated realms, and decided<br>to unify the oddly named scripts in a single 'gits' meta-repos tool, so I can<br>just symlink this script into my ~/bin and use it everywhere.<br><br>Change-Id: I579e7af26d76d5c5d83b2349695456bc7b54f5a2<br>---<br>M src/README<br>D src/e<br>D src/g<br>D src/git_branch_summary.py<br>A src/gits<br>D src/s<br>D src/st<br>7 files changed, 397 insertions(+), 298 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/README b/src/README</span><br><span>index a2fbe81..f066561 100644</span><br><span>--- a/src/README</span><br><span>+++ b/src/README</span><br><span>@@ -11,12 +11,11 @@</span><br><span>  Pass a patch number seen on gerrit to fetch the latest patch set into</span><br><span>        your git clone. See top comment in the script.</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ./g   run a git command in each source tree</span><br><span style="color: hsl(0, 100%, 40%);">- ./e   run an arbitrary shell command in each source tree</span><br><span style="color: hsl(0, 100%, 40%);">- ./st  show a brief branch and local mods status for each source tree</span><br><span style="color: hsl(0, 100%, 40%);">- ./s   walk through each source tree and use gitk as well as user interaction</span><br><span style="color: hsl(0, 100%, 40%);">-       to quickly fast-forward / reset changes coming in from upstream. (This</span><br><span style="color: hsl(0, 100%, 40%);">-       is potentially dangerous, but safe if you only hit enter every time.)</span><br><span style="color: hsl(120, 100%, 40%);">+ gits   Conveniently manage several git clones:</span><br><span style="color: hsl(120, 100%, 40%);">+        - run a git or shell command in each source tree</span><br><span style="color: hsl(120, 100%, 40%);">+ - show a brief branch and local mods status for each source tree</span><br><span style="color: hsl(120, 100%, 40%);">+      - merge / rebase / fast-forward each source tree interactively</span><br><span style="color: hsl(120, 100%, 40%);">+        See ./gits help</span><br><span> </span><br><span> Examples:</span><br><span> </span><br><span>@@ -54,7 +53,7 @@</span><br><span> </span><br><span> -----------------------------------------------------------------------------</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-./g fetch    # run 'git fetch' in each clone = fetch all from upstream</span><br><span style="color: hsl(120, 100%, 40%);">+./gits fetch    # run 'git fetch' in each clone = fetch all from upstream</span><br><span> </span><br><span> ===== libasn1c =====</span><br><span> remote: Counting objects: 29, done</span><br><span>@@ -90,7 +89,7 @@</span><br><span> </span><br><span> -----------------------------------------------------------------------------</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-./st         # any modifications / updates? (e.g. useful after './g fetch')</span><br><span style="color: hsl(120, 100%, 40%);">+./gits st    # any modifications / updates? (e.g. useful after './g fetch')</span><br><span>              # (checks only 'master' and the current checked-out branch)</span><br><span> </span><br><span>      libasn1c master</span><br><span>@@ -116,13 +115,13 @@</span><br><span> </span><br><span> -----------------------------------------------------------------------------</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-./e rm .version  # in each source tree, remove the local .version file</span><br><span style="color: hsl(120, 100%, 40%);">+./gits sh rm .version  # in each source tree, remove the local .version file</span><br><span> </span><br><span> -----------------------------------------------------------------------------</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-./s         # interactively try to fast-forward to upstream and/or save</span><br><span style="color: hsl(0, 100%, 40%);">-            # local modifications.</span><br><span style="color: hsl(0, 100%, 40%);">-            # If you just hit Enter all the time, nothing will be changed.</span><br><span style="color: hsl(120, 100%, 40%);">+./gits rebase  # interactively try to fast-forward to upstream and/or save</span><br><span style="color: hsl(120, 100%, 40%);">+               # local modifications.</span><br><span style="color: hsl(120, 100%, 40%);">+               # If you just hit Enter all the time, nothing dangerous will happen.</span><br><span> </span><br><span> </span><br><span> libosmocore</span><br><span>diff --git a/src/e b/src/e</span><br><span>deleted file mode 100755</span><br><span>index 4d32bf1..0000000</span><br><span>--- a/src/e</span><br><span>+++ /dev/null</span><br><span>@@ -1,15 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python3</span><br><span style="color: hsl(0, 100%, 40%);">-import os</span><br><span style="color: hsl(0, 100%, 40%);">-import os.path</span><br><span style="color: hsl(0, 100%, 40%);">-import sys</span><br><span style="color: hsl(0, 100%, 40%);">-import subprocess</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-base_dir = os.getcwd()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-for p in list(os.listdir('.')):</span><br><span style="color: hsl(0, 100%, 40%);">-        subdir = os.path.join(base_dir, p)</span><br><span style="color: hsl(0, 100%, 40%);">-      if not os.path.isdir(os.path.join(subdir, '.git')):</span><br><span style="color: hsl(0, 100%, 40%);">-             continue</span><br><span style="color: hsl(0, 100%, 40%);">-        print("\n===== %s =====" % p)</span><br><span style="color: hsl(0, 100%, 40%);">- os.chdir(subdir)</span><br><span style="color: hsl(0, 100%, 40%);">-        subprocess.call(sys.argv[1:])</span><br><span>diff --git a/src/g b/src/g</span><br><span>deleted file mode 100755</span><br><span>index bb9b693..0000000</span><br><span>--- a/src/g</span><br><span>+++ /dev/null</span><br><span>@@ -1,17 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python3</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-import sys</span><br><span style="color: hsl(0, 100%, 40%);">-import os</span><br><span style="color: hsl(0, 100%, 40%);">-import subprocess</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-git_subdirs = []</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-for subdir in os.listdir():</span><br><span style="color: hsl(0, 100%, 40%);">-  if not os.path.isdir(os.path.join(subdir, '.git')):</span><br><span style="color: hsl(0, 100%, 40%);">-    continue</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  print('\n===== %s =====' % subdir)</span><br><span style="color: hsl(0, 100%, 40%);">-  sys.stdout.flush()</span><br><span style="color: hsl(0, 100%, 40%);">-  subprocess.call(['git', '-C', subdir] + sys.argv[1:])</span><br><span style="color: hsl(0, 100%, 40%);">-  sys.stdout.flush()</span><br><span style="color: hsl(0, 100%, 40%);">-  sys.stderr.flush()</span><br><span>diff --git a/src/git_branch_summary.py b/src/git_branch_summary.py</span><br><span>deleted file mode 100755</span><br><span>index 9d81f8b..0000000</span><br><span>--- a/src/git_branch_summary.py</span><br><span>+++ /dev/null</span><br><span>@@ -1,68 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-import sys, subprocess, re</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if len(sys.argv) < 2:</span><br><span style="color: hsl(0, 100%, 40%);">-  print("Usage: %s <git_dir> [...]\nThis is mostly here for helping the 'st' script." % sys.argv[0])</span><br><span style="color: hsl(0, 100%, 40%);">-  exit(1)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-interesting_branch_names = [ 'master', 'sysmocom/iu', 'sysmocom/sccp', 'aper-prefix-onto-upstream' ]</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-re_branch_name = re.compile('^..([^ ]+) .*')</span><br><span style="color: hsl(0, 100%, 40%);">-re_ahead = re.compile('ahead [0-9]+|behind [0-9]+')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-def branch_name(line):</span><br><span style="color: hsl(0, 100%, 40%);">-  m = re_branch_name.match(line)</span><br><span style="color: hsl(0, 100%, 40%);">-  return m.group(1)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-interesting = []</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-def do_one_git(git_dir):</span><br><span style="color: hsl(0, 100%, 40%);">-  global interesting</span><br><span style="color: hsl(0, 100%, 40%);">-  branch_strs = subprocess.check_output(('git', '-C', git_dir, 'branch', '-vv')).decode('utf-8').splitlines()</span><br><span style="color: hsl(0, 100%, 40%);">-  interesting_branches = []</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  for line in branch_strs:</span><br><span style="color: hsl(0, 100%, 40%);">-    name = branch_name(line)</span><br><span style="color: hsl(0, 100%, 40%);">-    current_branch = False</span><br><span style="color: hsl(0, 100%, 40%);">-    if line.startswith('*'):</span><br><span style="color: hsl(0, 100%, 40%);">-      current_branch = True</span><br><span style="color: hsl(0, 100%, 40%);">-    elif name not in interesting_branch_names:</span><br><span style="color: hsl(0, 100%, 40%);">-      continue</span><br><span style="color: hsl(0, 100%, 40%);">-    ahead = re_ahead.findall(line)</span><br><span style="color: hsl(0, 100%, 40%);">-    if not ahead and not current_branch:</span><br><span style="color: hsl(0, 100%, 40%);">-      continue</span><br><span style="color: hsl(0, 100%, 40%);">-    ahead = [x.replace('ahead ', '+').replace('behind ', '-') for x in ahead]</span><br><span style="color: hsl(0, 100%, 40%);">-    br = (current_branch, name, ahead)</span><br><span style="color: hsl(0, 100%, 40%);">-    if current_branch:</span><br><span style="color: hsl(0, 100%, 40%);">-      interesting_branches.insert(0, br)</span><br><span style="color: hsl(0, 100%, 40%);">-    else:</span><br><span style="color: hsl(0, 100%, 40%);">-      interesting_branches.append(br)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  status = subprocess.check_output(('git', '-C', git_dir, 'status')).decode()</span><br><span style="color: hsl(0, 100%, 40%);">-  has_mods = 'modified:' in status</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  interesting.append((git_dir, has_mods, interesting_branches))</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-for git_dir in sys.argv[1:]:</span><br><span style="color: hsl(0, 100%, 40%);">-  do_one_git(git_dir)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-first_col = max([len(git_dir) for git_dir, _, _ in interesting])</span><br><span style="color: hsl(0, 100%, 40%);">-first_col_fmt = '%' + str(first_col) + 's'</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-for git_dir, has_mods, interesting_branches in interesting:</span><br><span style="color: hsl(0, 100%, 40%);">-  strs = [first_col_fmt % git_dir,]</span><br><span style="color: hsl(0, 100%, 40%);">-  if has_mods:</span><br><span style="color: hsl(0, 100%, 40%);">-    strs.append('MODS')</span><br><span style="color: hsl(0, 100%, 40%);">-  for current_branch, name, ahead in interesting_branches:</span><br><span style="color: hsl(0, 100%, 40%);">-    br = []</span><br><span style="color: hsl(0, 100%, 40%);">-    br.append(name)</span><br><span style="color: hsl(0, 100%, 40%);">-    if ahead:</span><br><span style="color: hsl(0, 100%, 40%);">-      br.append('[%s]' % '|'.join(ahead))</span><br><span style="color: hsl(0, 100%, 40%);">-    strs.append(''.join(br))</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  print(' '.join(strs))</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-# vim: shiftwidth=2 expandtab tabstop=2</span><br><span>diff --git a/src/gits b/src/gits</span><br><span>new file mode 100755</span><br><span>index 0000000..81083f1</span><br><span>--- /dev/null</span><br><span>+++ b/src/gits</span><br><span>@@ -0,0 +1,386 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python3</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# (C) 2018 by Neels Hofmeyr <neels@hofmeyr.de></span><br><span style="color: hsl(120, 100%, 40%);">+# All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# This program is free software: you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+# it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+# the Free Software Foundation, either version 3 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+# (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+# but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+# GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+# along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import sys</span><br><span style="color: hsl(120, 100%, 40%);">+import subprocess</span><br><span style="color: hsl(120, 100%, 40%);">+import re</span><br><span style="color: hsl(120, 100%, 40%);">+import argparse</span><br><span style="color: hsl(120, 100%, 40%);">+import os</span><br><span style="color: hsl(120, 100%, 40%);">+import shlex</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+doc = '''gits: conveniently manage several git subdirectories.</span><br><span style="color: hsl(120, 100%, 40%);">+Instead of doing the 'cd foo; git status; cd ../bar; git status' dance, this</span><br><span style="color: hsl(120, 100%, 40%);">+helps to save your time with: status, fetch, rebase, ...</span><br><span style="color: hsl(120, 100%, 40%);">+'''</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+re_status_mods = re.compile('^\t(modified|deleted):.*')</span><br><span style="color: hsl(120, 100%, 40%);">+re_status_branch_name = re.compile('On branch ([^ ]*)')</span><br><span style="color: hsl(120, 100%, 40%);">+re_branch_name = re.compile('^..([^ ]+) .*')</span><br><span style="color: hsl(120, 100%, 40%);">+re_ahead_behind = re.compile('ahead [0-9]+|behind [0-9]+')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def error(*msgs):</span><br><span style="color: hsl(120, 100%, 40%);">+    sys.stderr.write(''.join(msgs))</span><br><span style="color: hsl(120, 100%, 40%);">+    sys.stderr.write('\n')</span><br><span style="color: hsl(120, 100%, 40%);">+    exit(1)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def cmd_to_str(cmd):</span><br><span style="color: hsl(120, 100%, 40%);">+    return ' '.join(shlex.quote(c) for c in cmd)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def git(git_dir, *args, may_fail=False, section_marker=False, show_cmd=True):</span><br><span style="color: hsl(120, 100%, 40%);">+    sys.stdout.flush()</span><br><span style="color: hsl(120, 100%, 40%);">+    sys.stderr.flush()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if section_marker:</span><br><span style="color: hsl(120, 100%, 40%);">+        print('\n===== %s =====' % git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+        sys.stdout.flush()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    cmd = ['git', '-C', git_dir] + list(args)</span><br><span style="color: hsl(120, 100%, 40%);">+    if show_cmd:</span><br><span style="color: hsl(120, 100%, 40%);">+        print('+ %s' % cmd_to_str(cmd))</span><br><span style="color: hsl(120, 100%, 40%);">+        sys.stdout.flush()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = subprocess.call(cmd)</span><br><span style="color: hsl(120, 100%, 40%);">+    if rc and not may_fail:</span><br><span style="color: hsl(120, 100%, 40%);">+        error('git returned error! command: git -C %r %s' %</span><br><span style="color: hsl(120, 100%, 40%);">+              (git_dir, ' '.join(repr(arg) for arg in args)))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def git_output(git_dir, *args):</span><br><span style="color: hsl(120, 100%, 40%);">+    return subprocess.check_output(['git', '-C', git_dir, ] + list(args)).decode('utf-8')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def git_branch(git_dir):</span><br><span style="color: hsl(120, 100%, 40%);">+    status = git_output(git_dir, 'status', '--long')</span><br><span style="color: hsl(120, 100%, 40%);">+    m = re_status_branch_name.find(status)</span><br><span style="color: hsl(120, 100%, 40%);">+    if not m:</span><br><span style="color: hsl(120, 100%, 40%);">+        error('No current branch in %r' % git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+    return m.group(1)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def git_status(git_dir, verbose=False):</span><br><span style="color: hsl(120, 100%, 40%);">+    status_lines = git_output(git_dir, 'status').splitlines()</span><br><span style="color: hsl(120, 100%, 40%);">+    if verbose and len(status_lines):</span><br><span style="color: hsl(120, 100%, 40%);">+        print(status_lines[0])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    on_branch = None</span><br><span style="color: hsl(120, 100%, 40%);">+    branch_status_str = None</span><br><span style="color: hsl(120, 100%, 40%);">+    local_mods = False</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ON_BRANCH = 'On branch '</span><br><span style="color: hsl(120, 100%, 40%);">+    STATUS = 'Your branch'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    for l in status_lines:</span><br><span style="color: hsl(120, 100%, 40%);">+        if l.startswith(ON_BRANCH):</span><br><span style="color: hsl(120, 100%, 40%);">+            if on_branch:</span><br><span style="color: hsl(120, 100%, 40%);">+                error('cannot parse status, more than one branch?')</span><br><span style="color: hsl(120, 100%, 40%);">+            on_branch = l[len(ON_BRANCH):]</span><br><span style="color: hsl(120, 100%, 40%);">+        elif l.startswith(STATUS):</span><br><span style="color: hsl(120, 100%, 40%);">+            if 'Your branch is up to date' in l:</span><br><span style="color: hsl(120, 100%, 40%);">+                branch_status_str = l</span><br><span style="color: hsl(120, 100%, 40%);">+            elif 'Your branch is up-to-date' in l:</span><br><span style="color: hsl(120, 100%, 40%);">+                branch_status_str = l</span><br><span style="color: hsl(120, 100%, 40%);">+            elif 'Your branch is ahead' in l:</span><br><span style="color: hsl(120, 100%, 40%);">+                branch_status_str = 'ahead: ' + l</span><br><span style="color: hsl(120, 100%, 40%);">+            elif 'Your branch is behind' in l:</span><br><span style="color: hsl(120, 100%, 40%);">+                branch_status_str = 'behind: ' + l</span><br><span style="color: hsl(120, 100%, 40%);">+            elif 'have diverged' in l:</span><br><span style="color: hsl(120, 100%, 40%);">+                branch_status_str = 'diverged: ' + l</span><br><span style="color: hsl(120, 100%, 40%);">+            else:</span><br><span style="color: hsl(120, 100%, 40%);">+                error('unknown status str: %r' % l)</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            m = re_status_mods.match(l)</span><br><span style="color: hsl(120, 100%, 40%);">+            if m:</span><br><span style="color: hsl(120, 100%, 40%);">+                local_mods = True</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if verbose:</span><br><span style="color: hsl(120, 100%, 40%);">+        print('%s%s' % (branch_status_str, '\nLOCAL MODS' if local_mods else ''))</span><br><span style="color: hsl(120, 100%, 40%);">+    return (on_branch, branch_status_str, local_mods)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def git_branch_summary(git_dir):</span><br><span style="color: hsl(120, 100%, 40%);">+    '''return a list of strings: [git_dir, branch-info0, branch-info1,...]</span><br><span style="color: hsl(120, 100%, 40%);">+    infos are are arbitrary strings like "master[-1]"'''</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    interesting_branch_names = ('master',)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    strs = [git_dir, ]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    on_branch, branch_status_str, has_mods = git_status(git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if has_mods:</span><br><span style="color: hsl(120, 100%, 40%);">+        strs.append('MODS')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    branch_strs = git_output(git_dir, 'branch', '-vv').splitlines()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    for line in branch_strs:</span><br><span style="color: hsl(120, 100%, 40%);">+        m = re_branch_name.match(line)</span><br><span style="color: hsl(120, 100%, 40%);">+        name = m.group(1)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        current_branch = False</span><br><span style="color: hsl(120, 100%, 40%);">+        if line.startswith('*'):</span><br><span style="color: hsl(120, 100%, 40%);">+            current_branch = True</span><br><span style="color: hsl(120, 100%, 40%);">+        elif name not in interesting_branch_names:</span><br><span style="color: hsl(120, 100%, 40%);">+            continue</span><br><span style="color: hsl(120, 100%, 40%);">+        ahead_behind = re_ahead_behind.findall(line)</span><br><span style="color: hsl(120, 100%, 40%);">+        if not ahead_behind and not current_branch:</span><br><span style="color: hsl(120, 100%, 40%);">+            # skip branches that are "not interesting"</span><br><span style="color: hsl(120, 100%, 40%);">+            continue</span><br><span style="color: hsl(120, 100%, 40%);">+        ahead_behind = [</span><br><span style="color: hsl(120, 100%, 40%);">+            x.replace('ahead ', '+').replace('behind ', '-') for x in ahead_behind]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        branch_info = name</span><br><span style="color: hsl(120, 100%, 40%);">+        if ahead_behind:</span><br><span style="color: hsl(120, 100%, 40%);">+            branch_info = branch_info + ('[%s]' % '|'.join(ahead_behind))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        strs.append(''.join(branch_info))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return strs</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def format_summaries(summaries, sep0=' ', sep1=' '):</span><br><span style="color: hsl(120, 100%, 40%);">+    first_col = max([len(row[0]) for row in summaries])</span><br><span style="color: hsl(120, 100%, 40%);">+    first_col_fmt = '%' + str(first_col) + 's'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    lines = []</span><br><span style="color: hsl(120, 100%, 40%);">+    for row in summaries:</span><br><span style="color: hsl(120, 100%, 40%);">+        lines.append('%s%s%s' % (first_col_fmt %</span><br><span style="color: hsl(120, 100%, 40%);">+                                 row[0], sep0, sep1.join(row[1:])))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return '\n'.join(lines)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def git_dirs():</span><br><span style="color: hsl(120, 100%, 40%);">+    dirs = []</span><br><span style="color: hsl(120, 100%, 40%);">+    for sub in os.listdir():</span><br><span style="color: hsl(120, 100%, 40%);">+        git_path = os.path.join(sub, '.git')</span><br><span style="color: hsl(120, 100%, 40%);">+        if not os.path.isdir(git_path):</span><br><span style="color: hsl(120, 100%, 40%);">+            continue</span><br><span style="color: hsl(120, 100%, 40%);">+        dirs.append(sub)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if not dirs:</span><br><span style="color: hsl(120, 100%, 40%);">+        error('No subdirectories found that are git clones')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return list(sorted(dirs))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def print_status():</span><br><span style="color: hsl(120, 100%, 40%);">+    infos = [git_branch_summary(git_dir) for git_dir in git_dirs()]</span><br><span style="color: hsl(120, 100%, 40%);">+    print(format_summaries(infos))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def cmd_do(argv):</span><br><span style="color: hsl(120, 100%, 40%);">+    for git_dir in git_dirs():</span><br><span style="color: hsl(120, 100%, 40%);">+        git(git_dir, *argv, may_fail=True, section_marker=True)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def cmd_sh(cmd):</span><br><span style="color: hsl(120, 100%, 40%);">+    if not cmd:</span><br><span style="color: hsl(120, 100%, 40%);">+        error('which command do you want to run?')</span><br><span style="color: hsl(120, 100%, 40%);">+    for git_dir in git_dirs():</span><br><span style="color: hsl(120, 100%, 40%);">+        print('\n===== %s =====' % git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+        print('+ %s' % cmd_to_str(cmd))</span><br><span style="color: hsl(120, 100%, 40%);">+        sys.stdout.flush()</span><br><span style="color: hsl(120, 100%, 40%);">+        subprocess.call(cmd, cwd=git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+        sys.stdout.flush()</span><br><span style="color: hsl(120, 100%, 40%);">+        sys.stderr.flush()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class SkipThisRepo(Exception):</span><br><span style="color: hsl(120, 100%, 40%);">+    pass</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def ask(git_dir, *question, valid_answers=('*',)):</span><br><span style="color: hsl(120, 100%, 40%);">+    while True:</span><br><span style="color: hsl(120, 100%, 40%);">+        print('\n' + '\n  '.join(question))</span><br><span style="color: hsl(120, 100%, 40%);">+        print('  ' + '\n  '.join((</span><br><span style="color: hsl(120, 100%, 40%);">+            's  skip this repo',</span><br><span style="color: hsl(120, 100%, 40%);">+            't  show in tig',</span><br><span style="color: hsl(120, 100%, 40%);">+            'g  show in gitk',</span><br><span style="color: hsl(120, 100%, 40%);">+        )))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        answer = sys.stdin.readline().strip()</span><br><span style="color: hsl(120, 100%, 40%);">+        if answer == 's':</span><br><span style="color: hsl(120, 100%, 40%);">+            raise SkipThisRepo()</span><br><span style="color: hsl(120, 100%, 40%);">+        if answer == 't':</span><br><span style="color: hsl(120, 100%, 40%);">+            subprocess.call(('tig', '--all'), cwd=git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+            continue</span><br><span style="color: hsl(120, 100%, 40%);">+        if answer == 'g':</span><br><span style="color: hsl(120, 100%, 40%);">+            subprocess.call(('gitk', '--all'), cwd=git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+            continue</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        for v in valid_answers:</span><br><span style="color: hsl(120, 100%, 40%);">+            if v == answer:</span><br><span style="color: hsl(120, 100%, 40%);">+                return answer</span><br><span style="color: hsl(120, 100%, 40%);">+            if v == '*':</span><br><span style="color: hsl(120, 100%, 40%);">+                return answer</span><br><span style="color: hsl(120, 100%, 40%);">+            if v == '+' and len(answer):</span><br><span style="color: hsl(120, 100%, 40%);">+                return answer</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def rebase(git_dir):</span><br><span style="color: hsl(120, 100%, 40%);">+    orig_branch, branch_status_str, local_mods = git_status(</span><br><span style="color: hsl(120, 100%, 40%);">+        git_dir, verbose=True)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if orig_branch is None:</span><br><span style="color: hsl(120, 100%, 40%);">+        print('Not on a branch: %s' % git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+        raise SkipThisRepo()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if local_mods:</span><br><span style="color: hsl(120, 100%, 40%);">+        do_commit = ask(git_dir, 'Local mods.',</span><br><span style="color: hsl(120, 100%, 40%);">+                        'c  commit to this branch',</span><br><span style="color: hsl(120, 100%, 40%);">+                        '<name>  commit to new branch',</span><br><span style="color: hsl(120, 100%, 40%);">+                        '<empty> skip')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if not do_commit:</span><br><span style="color: hsl(120, 100%, 40%);">+            raise SkipThisRepo()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if do_commit == 'c':</span><br><span style="color: hsl(120, 100%, 40%);">+            git(git_dir, 'commit', '-am', 'wip', may_fail=True)</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            git(git_dir, 'checkout', '-b', do_commit)</span><br><span style="color: hsl(120, 100%, 40%);">+            git(git_dir, 'commit', '-am', 'wip', may_fail=True)</span><br><span style="color: hsl(120, 100%, 40%);">+            git(git_dir, 'checkout', orig_branch)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        _, _, local_mods = git_status(git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if local_mods:</span><br><span style="color: hsl(120, 100%, 40%);">+            print('There still are local modifications')</span><br><span style="color: hsl(120, 100%, 40%);">+            raise SkipThisRepo()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if branch_status_str is None:</span><br><span style="color: hsl(120, 100%, 40%);">+        print('there is no upstream branch for %r' % orig_branch)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    elif branch_status_str.startswith('behind'):</span><br><span style="color: hsl(120, 100%, 40%);">+        if 'and can be fast-forwarded' in branch_status_str:</span><br><span style="color: hsl(120, 100%, 40%);">+            print('fast-forwarding...')</span><br><span style="color: hsl(120, 100%, 40%);">+            git(git_dir, 'merge')</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            do_merge = ask(git_dir, 'Behind. git merge?',</span><br><span style="color: hsl(120, 100%, 40%);">+                           "<empty>  don't merge",</span><br><span style="color: hsl(120, 100%, 40%);">+                           'ok  git merge',</span><br><span style="color: hsl(120, 100%, 40%);">+                           valid_answers=('', 'ok')</span><br><span style="color: hsl(120, 100%, 40%);">+                           )</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            if do_merge == 'ok':</span><br><span style="color: hsl(120, 100%, 40%);">+                git(git_dir, 'merge')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    elif branch_status_str.startswith('ahead'):</span><br><span style="color: hsl(120, 100%, 40%);">+        do_commit = ask(git_dir, 'Ahead. commit to new branch?',</span><br><span style="color: hsl(120, 100%, 40%);">+                        '<empty>  no',</span><br><span style="color: hsl(120, 100%, 40%);">+                        '<name>   create new branch',</span><br><span style="color: hsl(120, 100%, 40%);">+                        )</span><br><span style="color: hsl(120, 100%, 40%);">+        if do_commit:</span><br><span style="color: hsl(120, 100%, 40%);">+            git(git_dir, 'checkout', '-b', do_commit)</span><br><span style="color: hsl(120, 100%, 40%);">+            git(git_dir, 'commit', '-am', 'wip', may_fail=True)</span><br><span style="color: hsl(120, 100%, 40%);">+            git(git_dir, 'checkout', orig_branch)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        do_reset = ask(git_dir, '%s: git reset --hard origin/%s?' % (orig_branch, orig_branch),</span><br><span style="color: hsl(120, 100%, 40%);">+                       '<empty>  no',</span><br><span style="color: hsl(120, 100%, 40%);">+                       'OK  yes (write OK in caps!)',</span><br><span style="color: hsl(120, 100%, 40%);">+                       valid_answers=('', 'OK'))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if do_reset == 'OK':</span><br><span style="color: hsl(120, 100%, 40%);">+            git(git_dir, 'reset', '--hard', 'origin/%s' % orig_branch)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    elif branch_status_str.startswith('diverged'):</span><br><span style="color: hsl(120, 100%, 40%);">+        do_reset = ask(git_dir, 'Diverged.',</span><br><span style="color: hsl(120, 100%, 40%);">+                       '%s: git reset --hard origin/%s?' % (</span><br><span style="color: hsl(120, 100%, 40%);">+                           orig_branch, orig_branch),</span><br><span style="color: hsl(120, 100%, 40%);">+                       '<empty>  no',</span><br><span style="color: hsl(120, 100%, 40%);">+                       'OK  yes (write OK in caps!)',</span><br><span style="color: hsl(120, 100%, 40%);">+                       valid_answers=('', 'OK'))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if do_reset == 'OK':</span><br><span style="color: hsl(120, 100%, 40%);">+            git(git_dir, 'reset', '--hard', 'origin/%s' % orig_branch)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    return orig_branch</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def cmd_rebase():</span><br><span style="color: hsl(120, 100%, 40%);">+    skipped = []</span><br><span style="color: hsl(120, 100%, 40%);">+    for git_dir in git_dirs():</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            print('\n\n===== %s =====' % git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+            sys.stdout.flush()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            branch = rebase(git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+            if branch != 'master':</span><br><span style="color: hsl(120, 100%, 40%);">+                git(git_dir, 'checkout', 'master')</span><br><span style="color: hsl(120, 100%, 40%);">+                rebase(git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+                git(git_dir, 'checkout', branch)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        except SkipThisRepo:</span><br><span style="color: hsl(120, 100%, 40%);">+            print('\nSkipping %r' % git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+            skipped.append(git_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    print('\n\n==========\nrebase done.\n')</span><br><span style="color: hsl(120, 100%, 40%);">+    print_status()</span><br><span style="color: hsl(120, 100%, 40%);">+    if skipped:</span><br><span style="color: hsl(120, 100%, 40%);">+        print('\nskipped: %s' % ' '.join(skipped))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def parse_args():</span><br><span style="color: hsl(120, 100%, 40%);">+    parser = argparse.ArgumentParser(description=doc)</span><br><span style="color: hsl(120, 100%, 40%);">+    sub = parser.add_subparsers(title='action', dest='action')</span><br><span style="color: hsl(120, 100%, 40%);">+    sub.required = True</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    # status</span><br><span style="color: hsl(120, 100%, 40%);">+    sub.add_parser('status', aliases=['st', 's'],</span><br><span style="color: hsl(120, 100%, 40%);">+                   help='show a branch summary and indicate modifications')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    # fetch</span><br><span style="color: hsl(120, 100%, 40%);">+    fetch = sub.add_parser('fetch', aliases=['f'],</span><br><span style="color: hsl(120, 100%, 40%);">+                           help="run 'git fetch' in each clone (use before rebase)")</span><br><span style="color: hsl(120, 100%, 40%);">+    fetch.add_argument('remainder', nargs=argparse.REMAINDER,</span><br><span style="color: hsl(120, 100%, 40%);">+                       help='additional arguments to be passed to git fetch')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    # rebase</span><br><span style="color: hsl(120, 100%, 40%);">+    sub.add_parser('rebase', aliases=['r', 're'],</span><br><span style="color: hsl(120, 100%, 40%);">+                   help='interactively ff-merge master, rebase current branches')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    # sh</span><br><span style="color: hsl(120, 100%, 40%);">+    sh = sub.add_parser('sh',</span><br><span style="color: hsl(120, 100%, 40%);">+                        help='run shell command in each clone (`gits sh echo hi`)')</span><br><span style="color: hsl(120, 100%, 40%);">+    sh.add_argument('remainder', nargs=argparse.REMAINDER,</span><br><span style="color: hsl(120, 100%, 40%);">+                    help='command to run in each clone')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    # do</span><br><span style="color: hsl(120, 100%, 40%);">+    do = sub.add_parser('do',</span><br><span style="color: hsl(120, 100%, 40%);">+                        help='run git command in each clone (`gits do clean -dxf`)')</span><br><span style="color: hsl(120, 100%, 40%);">+    do.add_argument('remainder', nargs=argparse.REMAINDER,</span><br><span style="color: hsl(120, 100%, 40%);">+                    help='git command to run in each clone')</span><br><span style="color: hsl(120, 100%, 40%);">+    return parser.parse_args()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == '__main__':</span><br><span style="color: hsl(120, 100%, 40%);">+    args = parse_args()</span><br><span style="color: hsl(120, 100%, 40%);">+    if args.action in ['status', 's', 'st']:</span><br><span style="color: hsl(120, 100%, 40%);">+        print_status()</span><br><span style="color: hsl(120, 100%, 40%);">+    elif args.action in ['fetch', 'f']:</span><br><span style="color: hsl(120, 100%, 40%);">+        cmd_do(['fetch'] + args.remainder)</span><br><span style="color: hsl(120, 100%, 40%);">+    elif args.action in ['rebase', 'r']:</span><br><span style="color: hsl(120, 100%, 40%);">+        cmd_rebase()</span><br><span style="color: hsl(120, 100%, 40%);">+    elif args.action == 'sh':</span><br><span style="color: hsl(120, 100%, 40%);">+        cmd_sh(args.remainder)</span><br><span style="color: hsl(120, 100%, 40%);">+    elif args.action == 'do':</span><br><span style="color: hsl(120, 100%, 40%);">+        cmd_do(args.remainder)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# vim: shiftwidth=4 expandtab tabstop=4</span><br><span>diff --git a/src/s b/src/s</span><br><span>deleted file mode 100755</span><br><span>index f897bc1..0000000</span><br><span>--- a/src/s</span><br><span>+++ /dev/null</span><br><span>@@ -1,176 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env bash</span><br><span style="color: hsl(0, 100%, 40%);">-fastforwards=""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-Git() {</span><br><span style="color: hsl(0, 100%, 40%);">-  echo "git $@"</span><br><span style="color: hsl(0, 100%, 40%);">-  git $@</span><br><span style="color: hsl(0, 100%, 40%);">-  if [ "$?" != "0" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-    echo "GIT RETURNED ERROR!"</span><br><span style="color: hsl(0, 100%, 40%);">-    exit 1</span><br><span style="color: hsl(0, 100%, 40%);">-  fi</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-Git_may_fail() {</span><br><span style="color: hsl(0, 100%, 40%);">-  git $@</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-Git_branch() {</span><br><span style="color: hsl(0, 100%, 40%);">-  echo "$(Git -C "$dir" status)" | grep 'On branch' | sed 's/On branch //'</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-gitk_start() {</span><br><span style="color: hsl(0, 100%, 40%);">-  if [ -n "$DISPLAY" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-    gitk --all &</span><br><span style="color: hsl(0, 100%, 40%);">-    gitk_started="1"</span><br><span style="color: hsl(0, 100%, 40%);">-  fi</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-status() {</span><br><span style="color: hsl(0, 100%, 40%);">-  st="$(Git status)"</span><br><span style="color: hsl(0, 100%, 40%);">-  mods="$(echo "$st" | grep 'modified:')"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  stline="$(echo "$st" | grep '\(behind\|ahead\|up-to-date\|diverged\)')"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  echo "$br"</span><br><span style="color: hsl(0, 100%, 40%);">-  echo "$stline"</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-dance() {</span><br><span style="color: hsl(0, 100%, 40%);">-  echo</span><br><span style="color: hsl(0, 100%, 40%);">-  echo</span><br><span style="color: hsl(0, 100%, 40%);">-  br="$(Git_branch)"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  echo "$dir"</span><br><span style="color: hsl(0, 100%, 40%);">-  cd "$dir"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  status</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if [ -z "$mods" -a -n "$(echo "$stline" | grep up-to-date)" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-    return 0</span><br><span style="color: hsl(0, 100%, 40%);">-  fi</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  gitk_start</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if [ -n "$mods" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-    echo "Local mods"</span><br><span style="color: hsl(0, 100%, 40%);">-    echo "$mods"</span><br><span style="color: hsl(0, 100%, 40%);">-    echo</span><br><span style="color: hsl(0, 100%, 40%);">-    echo "commit to new branch? (enter name, empty = no)"</span><br><span style="color: hsl(0, 100%, 40%);">-    read wipbranch</span><br><span style="color: hsl(0, 100%, 40%);">-    if [ -n "$wipbranch" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-      Git checkout -b "$wipbranch"</span><br><span style="color: hsl(0, 100%, 40%);">-      Git_may_fail commit -am wip</span><br><span style="color: hsl(0, 100%, 40%);">-      #Git push --set-upstream origin "$wipbranch"</span><br><span style="color: hsl(0, 100%, 40%);">-      Git checkout "$br"</span><br><span style="color: hsl(0, 100%, 40%);">-    else</span><br><span style="color: hsl(0, 100%, 40%);">-      echo "commit to this branch $br ?  (empty = no, 'ok' = yes)"</span><br><span style="color: hsl(0, 100%, 40%);">-      read ok</span><br><span style="color: hsl(0, 100%, 40%);">-      if [ "x$ok" = xok ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-        Git commit -am wip</span><br><span style="color: hsl(0, 100%, 40%);">-        #Git push</span><br><span style="color: hsl(0, 100%, 40%);">-      fi</span><br><span style="color: hsl(0, 100%, 40%);">-    fi</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    status</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if [ -n "$mods" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-      return 0</span><br><span style="color: hsl(0, 100%, 40%);">-    fi</span><br><span style="color: hsl(0, 100%, 40%);">-  fi</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if [ -n "$(echo "$stline" | grep behind)" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-    if [ -n "$(echo "$stline" | grep "and can be fast-forwarded")" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-      echo "fast forwarding..."</span><br><span style="color: hsl(0, 100%, 40%);">-      fastforwards="${fastforwards} $dir/$br:$(Git_may_fail rev-parse --short HEAD)"</span><br><span style="color: hsl(0, 100%, 40%);">-      ok="ok"</span><br><span style="color: hsl(0, 100%, 40%);">-    else</span><br><span style="color: hsl(0, 100%, 40%);">-      echo "Behind. git merge?  (empty = no, 'ok' = yes)"</span><br><span style="color: hsl(0, 100%, 40%);">-      read ok</span><br><span style="color: hsl(0, 100%, 40%);">-    fi</span><br><span style="color: hsl(0, 100%, 40%);">-    if [ "x$ok" = xok ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-      Git merge</span><br><span style="color: hsl(0, 100%, 40%);">-    fi</span><br><span style="color: hsl(0, 100%, 40%);">-  elif [ -n "$(echo "$stline" | grep ahead)" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-    echo "Ahead. commit to new branch? (enter name, empty = no)"</span><br><span style="color: hsl(0, 100%, 40%);">-    read wipbranch</span><br><span style="color: hsl(0, 100%, 40%);">-    if [ -n "$wipbranch" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-      Git checkout -b "$wipbranch"</span><br><span style="color: hsl(0, 100%, 40%);">-      Git_may_fail commit -am wip</span><br><span style="color: hsl(0, 100%, 40%);">-      #Git push --set-upstream origin "$wipbranch"</span><br><span style="color: hsl(0, 100%, 40%);">-      Git checkout "$br"</span><br><span style="color: hsl(0, 100%, 40%);">-    fi</span><br><span style="color: hsl(0, 100%, 40%);">-    echo "$br: git reset --hard origin/$br ?  (empty = no, 'OK' IN CAPS = yes)"</span><br><span style="color: hsl(0, 100%, 40%);">-    read ok</span><br><span style="color: hsl(0, 100%, 40%);">-    if [ "x$ok" = xOK ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-      Git reset --hard "origin/$br"</span><br><span style="color: hsl(0, 100%, 40%);">-    fi</span><br><span style="color: hsl(0, 100%, 40%);">-    return 0</span><br><span style="color: hsl(0, 100%, 40%);">-  elif [ -n "$(echo "$stline" | grep diverged)" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-    echo "Diverged. git reset --hard origin/$br ?  (empty = no, 'OK' IN CAPS = yes)"</span><br><span style="color: hsl(0, 100%, 40%);">-    read ok</span><br><span style="color: hsl(0, 100%, 40%);">-    if [ "x$ok" = xOK ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-      wipbranch="neels/wip_$(date +%Y%m%d_%H%M)"</span><br><span style="color: hsl(0, 100%, 40%);">-      Git checkout -b "$wipbranch"</span><br><span style="color: hsl(0, 100%, 40%);">-      Git_may_fail commit -am wip</span><br><span style="color: hsl(0, 100%, 40%);">-      Git checkout "$br"</span><br><span style="color: hsl(0, 100%, 40%);">-      Git reset --hard "origin/$br"</span><br><span style="color: hsl(0, 100%, 40%);">-    fi</span><br><span style="color: hsl(0, 100%, 40%);">-  elif [ -z "$(echo "$stline" | grep up-to-date)" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-    echo "Nothing to do."</span><br><span style="color: hsl(0, 100%, 40%);">-    echo "$st"</span><br><span style="color: hsl(0, 100%, 40%);">-  fi</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-kill_gitk() {</span><br><span style="color: hsl(0, 100%, 40%);">-  if [ "$gitk_started" = "1" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-    kill %1</span><br><span style="color: hsl(0, 100%, 40%);">-    gitk_started="0"</span><br><span style="color: hsl(0, 100%, 40%);">-  fi</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-basedir="$(pwd)"</span><br><span style="color: hsl(0, 100%, 40%);">-gitk_started="0"</span><br><span style="color: hsl(0, 100%, 40%);">-for gitdir in */.git ; do</span><br><span style="color: hsl(0, 100%, 40%);">-  cd "$basedir"</span><br><span style="color: hsl(0, 100%, 40%);">-  dir="$(dirname "$gitdir")"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  orig_branch="$(Git_branch)"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  kill_gitk</span><br><span style="color: hsl(0, 100%, 40%);">-  dance</span><br><span style="color: hsl(0, 100%, 40%);">-  cd "$basedir"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if [ "$orig_branch" != master ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-       kill_gitk</span><br><span style="color: hsl(0, 100%, 40%);">-       git -C "$dir" checkout master || continue</span><br><span style="color: hsl(0, 100%, 40%);">-     dance</span><br><span style="color: hsl(0, 100%, 40%);">-   cd "$basedir"</span><br><span style="color: hsl(0, 100%, 40%);">- pwd</span><br><span style="color: hsl(0, 100%, 40%);">-     git -C "$dir" checkout "$orig_branch"</span><br><span style="color: hsl(0, 100%, 40%);">-  fi</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#  if [ "$dir" = "openbsc" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-#    kill_gitk</span><br><span style="color: hsl(0, 100%, 40%);">-#    Git checkout "sysmocom/iu"</span><br><span style="color: hsl(0, 100%, 40%);">-#    dance</span><br><span style="color: hsl(0, 100%, 40%);">-#  fi</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  sleep .1</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-done</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-kill_gitk</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-echo</span><br><span style="color: hsl(0, 100%, 40%);">-echo</span><br><span style="color: hsl(0, 100%, 40%);">-./st</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if [ -n "$fastforwards" ]; then</span><br><span style="color: hsl(0, 100%, 40%);">-  echo</span><br><span style="color: hsl(0, 100%, 40%);">-  echo "FAST-FORWARDED: $fastforwards"</span><br><span style="color: hsl(0, 100%, 40%);">-fi</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-# vim: shiftwidth=2 expandtab</span><br><span>diff --git a/src/st b/src/st</span><br><span>deleted file mode 100755</span><br><span>index a47de6b..0000000</span><br><span>--- a/src/st</span><br><span>+++ /dev/null</span><br><span>@@ -1,10 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/bin/sh</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-git_dirs() {</span><br><span style="color: hsl(0, 100%, 40%);">-  for gitdir in */.git ; do</span><br><span style="color: hsl(0, 100%, 40%);">-    echo "$(dirname "$gitdir")"</span><br><span style="color: hsl(0, 100%, 40%);">-  done</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-./git_branch_summary.py $(git_dirs)</span><br><span style="color: hsl(0, 100%, 40%);">-# vim: shiftwidth=2 expandtab</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/11560">change 11560</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/11560"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-dev </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I579e7af26d76d5c5d83b2349695456bc7b54f5a2 </div>
<div style="display:none"> Gerrit-Change-Number: 11560 </div>
<div style="display:none"> Gerrit-PatchSet: 11 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: osmith <osmith@sysmocom.de> </div>