| |
@@ -2,7 +2,7 @@
|
| |
|
| |
"""This script checks if a branch may be deleted.
|
| |
|
| |
- A branch may be removed safely when, for all commits in that branch
|
| |
+ 1. A branch may be removed safely when, for all commits in that branch
|
| |
not reachable from other branches, there are no complete koji builds.
|
| |
|
| |
Examples:
|
| |
@@ -20,6 +20,29 @@
|
| |
'B' has commits that are not found anywhere else (B, B', and B"), and
|
| |
we need to check in koji if it knows about any builds from those
|
| |
commits.
|
| |
+
|
| |
+ 2. Release branches are protected: as an additional constraint,
|
| |
+ release branches (fNN, elN, epelN, …) cannot be deleted if any builds
|
| |
+ were done for this release. This means we preserve the branch
|
| |
+ identification, even if we don't need this to preserve commits.
|
| |
+
|
| |
+ For branches older than f21, bodhi information is not available and we
|
| |
+ cannot check if builds have been performed, so this script always
|
| |
+ refuses removal.
|
| |
+
|
| |
+ Removal of the 'master' branch is always refused.
|
| |
+
|
| |
+ 3. Removal is refused in some additional corner cases:
|
| |
+ - the spec file cannot be parsed
|
| |
+ - multiple spec files are found
|
| |
+ - any modular builds exists
|
| |
+
|
| |
+ Note: when *branch* is specified as a remote branch (e.g. "origin/f33"),
|
| |
+ remote branches are checked. This mode is useful when run in a clone
|
| |
+ of the canonical origin repository. When *branch* is specified as a
|
| |
+ local branch, local branches are checked. This mode is useful when run
|
| |
+ in the original repo.
|
| |
+
|
| |
"""
|
| |
|
| |
import argparse
|
| |
@@ -108,6 +131,14 @@
|
| |
by_hash = {find_hash(b):b for b in builds if b['source']}
|
| |
return by_hash
|
| |
|
| |
+ def mbs_builds_exist(builds):
|
| |
+ for name in builds:
|
| |
+ for build in builds[name].values():
|
| |
+ if build.get('owner_name', None) == 'mbs/mbs.fedoraproject.org':
|
| |
+ print(f"Modular build {build['nvr']} found.")
|
| |
+ return True
|
| |
+ return False
|
| |
+
|
| |
def containing_branches(repo, commit, *, local, ignore_branch=None):
|
| |
if local:
|
| |
containing = repo.branches.local.with_commit(commit)
|
| |
@@ -197,14 +228,20 @@
|
| |
print('Branch was used to build packages, cannot delete.')
|
| |
return 1
|
| |
|
| |
+ print('Querying koji for builds...')
|
| |
+ builds = {opts.package: list_builds(opts.package, opts)}
|
| |
+
|
| |
+ if mbs_builds_exist(builds):
|
| |
+ print('Package was used in modular builds, this script is not smart enough.')
|
| |
+ return 1
|
| |
+
|
| |
other = list(containing_branches(repo, branch.target, local=local, ignore_branch=branch))
|
| |
if other:
|
| |
names = ', '.join(o.name for o in other)
|
| |
print(f'Branch merged into {names}. Safe to delete.')
|
| |
return 0
|
| |
|
| |
- print('Branch has commits not found anywhere else. Looking for builds.')
|
| |
- builds = {opts.package: list_builds(opts.package, opts)}
|
| |
+ print('Branch has commits not found anywhere else, checking builds...')
|
| |
|
| |
for n, commit in enumerate(repo.walk(branch.target, pygit2.GIT_SORT_TOPOLOGICAL)):
|
| |
subj = commit.message.splitlines()[0][:60]
|
| |
s/master/default/ ?