Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 53 additions & 4 deletions pushpatches.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
'SubprocessResult', 'stdout stderr returncode')
TracTicketData = collections.namedtuple(
'TracTicketData', 'id time_created time_changed attributes')

OidEntry = collections.namedtuple(
'OidEntry', 'oid name')

def cleanpath(path):
"""Return absolute path with leading ~ expanded"""
Expand Down Expand Up @@ -155,6 +156,14 @@ def add_reviewer(self, reviewer):
self.head_lines.append('\n')
self.head_lines.append('Reviewed-By: %s\n' % reviewer)

@property
def modified_oids(self):
oid_regex = ("^\+(attributeTypes|objectClasses): "
"\((?P<oid>[\d.]+) NAME '(?P<name>\w+)")
data = ''.join(self.patch_lines)
for match in re.finditer(oid_regex, data, re.MULTILINE):
yield OidEntry(match.group('oid'), match.group('name'))

@property
def lines(self):
yield from self.head_lines
Expand Down Expand Up @@ -277,12 +286,17 @@ def runcommand(self, *argv, check_stdout=None, check_stderr=None,
self.die('Git command failed')
return SubprocessResult(stdout, stderr, returncode)

def ensure_clean_repo(self):
def ensure_clean_repo(self, git_dir=None, work_tree=None):
"""Make sure the working tree matches the git index"""
self.git('status', '--porcelain',
args = ['--git-dir', git_dir] if git_dir else []
args += ['--work-tree', work_tree] if work_tree else []
args += ['status', '--porcelain']

self.git(*args,
check_stdout='',
check_stderr='',
fail_message='Repository %s not clean' % os.getcwd())
fail_message='Repository %s not clean'
% git_dir or os.getcwd())

def get_rewiewers(self, tickets):
"""Get reviewer name & address, or None for --no-reviewer
Expand Down Expand Up @@ -346,6 +360,30 @@ def apply_patches(self, patches, branch):
print('Resulting hash: %s' % sha1)
return sha1

def is_oid_registered(self, oid_entry):
oid_git = cleanpath(self.config.get('oid-git'))
oid = oid_entry.oid
name = oid_entry.name

if oid_git:
oid_git_path = os.path.join(oid_git, '.git/')
self.ensure_clean_repo(git_dir=oid_git_path, work_tree=oid_git)

result = self.git('--git-dir', oid_git_path,
'--work-tree', oid_git,
'grep', oid,
check_returncode=None)
if result.returncode != 0:
print("OID %s (%s) is not registered" % (oid, name))
return False
elif name not in result.stdout:
print("OID %s (%s) clashes with:" % (oid, name))
print(result.stdout)
return False
else:
print("OID %s (%s) correctly registered" % (oid, name))
return True

def print_push_info(self, patches, sha1s, ticket_numbers, tickets):
"""Print lots of info about the to-be-pushed commits"""
remote = self.config['remote']
Expand Down Expand Up @@ -441,6 +479,17 @@ def run(self):
else:
print('Reviewer: None')

# Check the OIDs
if not self.options.get('--no-oid-check', False):
if self.config.get('oid-git'):
missing_oids = [oid_entry for p in patches
for oid_entry in p.modified_oids
if not self.is_oid_registered(oid_entry)]
if missing_oids:
self.die('OIDs in the patcheset are not registered')
else:
print('The oid-git option not found, skipping the OID check.')

branches = self.options['--branch']
if not branches:
if not tickets:
Expand Down