aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--b4/__init__.py52
-rw-r--r--b4/command.py4
-rw-r--r--b4/mbox.py19
3 files changed, 46 insertions, 29 deletions
diff --git a/b4/__init__.py b/b4/__init__.py
index 53eaf27..9a18d00 100644
--- a/b4/__init__.py
+++ b/b4/__init__.py
@@ -630,7 +630,7 @@ class LoreSeries:
return msgs
- def check_applies_clean(self, gitdir, at='HEAD'):
+ def check_applies_clean(self, gitdir: str, at: Optional[str] = None) -> Tuple[int, list]:
if self._indexes is None:
self._indexes = list()
seenfiles = set()
@@ -649,6 +649,8 @@ class LoreSeries:
self._indexes.append((fn, bh))
mismatches = list()
+ if at is None:
+ at = 'HEAD'
for fn, bh in self._indexes:
ecode, out = git_run_command(gitdir, ['ls-tree', at, fn])
if ecode == 0 and len(out):
@@ -665,7 +667,7 @@ class LoreSeries:
return len(self._indexes), mismatches
- def find_base(self, gitdir: str, branches: str = 'HEAD', maxdays: int = 30) -> Tuple[str, len]:
+ def find_base(self, gitdir: str, branches: Optional[str] = None, maxdays: int = 30) -> Tuple[str, len, len]:
# Find the date of the first patch we have
pdate = datetime.datetime.now()
for lmsg in self.patches:
@@ -676,7 +678,12 @@ class LoreSeries:
# Find latest commit on that date
guntil = pdate.strftime('%Y-%m-%d')
- gitargs = ['log', '--pretty=oneline', '--until', guntil, '--max-count=1', '--branches', branches]
+ if branches:
+ where = ['--branches', branches]
+ else:
+ where = ['--all']
+
+ gitargs = ['log', '--pretty=oneline', '--until', guntil, '--max-count=1'] + where
lines = git_get_command_lines(gitdir, gitargs)
if not lines:
raise IndexError
@@ -689,34 +696,41 @@ class LoreSeries:
logger.debug('Starting --find-object from %s to %s', gsince, guntil)
best = commit
for fn, bi in mismatches:
- logger.debug('Finding tree matching %s=%s in %s', fn, bi, branches)
- gitargs = ['log', '-m', '--pretty=oneline', '--since', gsince, '--until', guntil,
- '--max-count=1', '--find-object', bi, '--branches', branches]
+ logger.debug('Finding tree matching %s=%s in %s', fn, bi, where)
+ gitargs = ['log', '--pretty=oneline', '--since', gsince, '--until', guntil,
+ '--find-object', bi] + where
lines = git_get_command_lines(gitdir, gitargs)
if not lines:
logger.debug('Could not find object %s in the tree', bi)
continue
- commit = lines[0].split()[0]
- logger.debug('commit=%s', commit)
- # We try both that commit and the one preceding it, in case it was a delete
- # Keep track of the fewest mismatches
- for tc in [commit, f'{commit}~1']:
- sc, sm = self.check_applies_clean(gitdir, tc)
- if len(sm) < fewest and len(sm) != sc:
- fewest = len(sm)
- best = tc
- logger.debug('fewest=%s, best=%s', fewest, best)
+ for line in lines:
+ commit = line.split()[0]
+ logger.debug('commit=%s', commit)
+ # We try both that commit and the one preceding it, in case it was a delete
+ # Keep track of the fewest mismatches
+ for tc in [commit, f'{commit}~1']:
+ sc, sm = self.check_applies_clean(gitdir, tc)
+ if len(sm) < fewest and len(sm) != sc:
+ fewest = len(sm)
+ best = tc
+ logger.debug('fewest=%s, best=%s', fewest, best)
+ if fewest == 0:
+ break
if fewest == 0:
break
-
+ if fewest == 0:
+ break
if fewest == 0:
break
else:
best = commit
+ if fewest == len(self._indexes):
+ # None of the blobs matched
+ raise IndexError
- lines = git_get_command_lines(gitdir, ['describe', best])
+ lines = git_get_command_lines(gitdir, ['describe', '--all', best])
if len(lines):
- return lines[0], fewest
+ return lines[0], len(self._indexes), fewest
raise IndexError
diff --git a/b4/command.py b/b4/command.py
index ebbb361..5bb3384 100644
--- a/b4/command.py
+++ b/b4/command.py
@@ -120,8 +120,8 @@ def cmd():
'"-P *globbing*" to match on commit subject)')
sp_am.add_argument('-g', '--guess-base', dest='guessbase', action='store_true', default=False,
help='Try to guess the base of the series (if not specified)')
- sp_am.add_argument('-b', '--guess-branch', dest='guessbranch', default='HEAD',
- help='When guessing base, use this branch instead of HEAD (use with -g)')
+ sp_am.add_argument('-b', '--guess-branch', dest='guessbranch', default=None,
+ help='When guessing base, restrict to this branch (use with -g)')
sp_am.add_argument('--guess-lookback', dest='guessdays', type=int, default=14,
help='When guessing base, go back this many days from the date of the patch')
sp_am.add_argument('-3', '--prep-3way', dest='threeway', action='store_true', default=False,
diff --git a/b4/mbox.py b/b4/mbox.py
index 98bd920..7adfecd 100644
--- a/b4/mbox.py
+++ b/b4/mbox.py
@@ -230,23 +230,26 @@ def make_am(msgs, cmdargs, msgid):
logger.critical(' Base: %s', base_commit)
else:
if topdir is not None:
+ guessed = False
checked, mismatches = lser.check_applies_clean(topdir, at=cmdargs.guessbranch)
if len(mismatches) == 0 and checked != mismatches:
+ guessed = True
logger.critical(' Base: current tree')
- elif len(mismatches) and cmdargs.guessbase:
+ if not guessed and cmdargs.guessbase:
logger.critical(' attempting to guess base-commit...')
try:
- base_commit, mismatches = lser.find_base(topdir, branches=cmdargs.guessbranch,
- maxdays=cmdargs.guessdays)
+ base_commit, nblobs, mismatches = lser.find_base(topdir, branches=cmdargs.guessbranch,
+ maxdays=cmdargs.guessdays)
if mismatches == 0:
logger.critical(' Base: %s (exact match)', base_commit)
+ elif nblobs == mismatches:
+ logger.critical(' Base: failed to guess base')
else:
- logger.critical(' Base: %s (best guess, %s blobs not matched)', base_commit,
- mismatches)
+ logger.critical(' Base: %s (best guess, %s/%s blobs matched)', base_commit,
+ nblobs-mismatches, nblobs)
except IndexError:
- logger.critical(' Base: not specified')
- pass
- else:
+ logger.critical(' Base: failed to guess base')
+ elif not cmdargs.guessbase:
logger.critical(' Base: not specified')
else:
logger.critical(' Base: not specified')