Merge branch 'master' into shadow
This commit is contained in:
commit
9af88e0f4b
5 changed files with 74 additions and 14 deletions
|
|
@ -443,7 +443,7 @@ class BuildRoot(object):
|
|||
def getUploadPath(self):
|
||||
"""Get the path that should be used when uploading files to
|
||||
the hub."""
|
||||
return 'tasks/%i' % self.task_id
|
||||
return koji.pathinfo.taskrelpath(self.task_id)
|
||||
|
||||
def uploadDir(self, dirpath, suffix=None):
|
||||
"""Upload the contents of the given directory to the
|
||||
|
|
@ -1176,7 +1176,7 @@ class BaseTaskHandler(object):
|
|||
# handle named parameters
|
||||
self.params,self.opts = koji.decode_args(*params)
|
||||
if workdir is None:
|
||||
workdir = "%s/tasks/%s" % (options.workdir, id)
|
||||
workdir = "%s/%s" % (options.workdir, koji.pathinfo.taskrelpath(id))
|
||||
self.workdir = workdir
|
||||
self.logger = logging.getLogger("koji.build.BaseTaskHandler")
|
||||
|
||||
|
|
@ -1288,7 +1288,7 @@ class BaseTaskHandler(object):
|
|||
return dict(session.host.taskWaitResults(self.id,subtasks))
|
||||
|
||||
def getUploadDir(self):
|
||||
return 'tasks/%i' % self.id
|
||||
return koji.pathinfo.taskrelpath(self.id)
|
||||
|
||||
def uploadFile(self, filename, remoteName=None):
|
||||
"""Upload the file with the given name to the task output directory
|
||||
|
|
|
|||
56
cli/koji
56
cli/koji
|
|
@ -1219,6 +1219,14 @@ def handle_prune_signed_copies(options, session, args):
|
|||
parser.add_option("--days", type="int", default=5, help=_("Timeout before clearing"))
|
||||
parser.add_option("-p", "--package", "--pkg", help=_("Limit to a single package"))
|
||||
parser.add_option("-b", "--build", help=_("Limit to a single build"))
|
||||
parser.add_option("-i", "--ignore-tag", action="append", default=[],
|
||||
help=_("Ignore these tags when considering whether a build is/was latest"))
|
||||
parser.add_option("--ignore-tag-file",
|
||||
help=_("File to read tag ignore patterns from"))
|
||||
parser.add_option("-r", "--protect-tag", action="append", default=[],
|
||||
help=_("Do not prune signed copies from matching tags"))
|
||||
parser.add_option("--protect-tag-file",
|
||||
help=_("File to read tag protect patterns from"))
|
||||
parser.add_option("--trashcan-tag", default="trashcan", help=_("Specify trashcan tag"))
|
||||
parser.add_option("--debug", action="store_true", help=_("Show debugging output"))
|
||||
(options, args) = parser.parse_args(args)
|
||||
|
|
@ -1232,6 +1240,14 @@ def handle_prune_signed_copies(options, session, args):
|
|||
#for now, we're just implementing mode #1
|
||||
#(with the modification that we check to see if the build was latest within
|
||||
#the last N days)
|
||||
if options.ignore_tag_file:
|
||||
fo = file(options.ignore_tag_file)
|
||||
options.ignore_tag.extend([line.strip() for line in fo.readlines()])
|
||||
fo.close()
|
||||
if options.protect_tag_file:
|
||||
fo = file(options.protect_tag_file)
|
||||
options.protect_tag.extend([line.strip() for line in fo.readlines()])
|
||||
fo.close()
|
||||
if options.debug:
|
||||
options.verbose = True
|
||||
cutoff_ts = time.time() - options.days * 24 * 3600
|
||||
|
|
@ -1280,6 +1296,7 @@ def handle_prune_signed_copies(options, session, args):
|
|||
print "DEBUG: %s" % nvr
|
||||
#see how recently this build was latest for a tag
|
||||
is_latest = False
|
||||
is_protected = False
|
||||
last_latest = None
|
||||
tags = {}
|
||||
for entry in session.tagHistory(build=binfo['id']):
|
||||
|
|
@ -1293,6 +1310,15 @@ def handle_prune_signed_copies(options, session, args):
|
|||
if options.debug:
|
||||
print "Ignoring trashcan tag for build %s" % nvr
|
||||
continue
|
||||
ignore_tag = False
|
||||
for pattern in options.ignore_tag:
|
||||
if fnmatch.fnmatch(tag_name, pattern):
|
||||
if options.debug:
|
||||
print "Ignoring tag %s for build %s" % (tag_name, nvr)
|
||||
ignore_tag = True
|
||||
break
|
||||
if ignore_tag:
|
||||
continue
|
||||
#in order to determine how recently this build was latest, we have
|
||||
#to look at the tagging history.
|
||||
hist = session.tagHistory(tag=tag_name, package=binfo['name'])
|
||||
|
|
@ -1319,8 +1345,9 @@ def handle_prune_signed_copies(options, session, args):
|
|||
if not latest_ts:
|
||||
#really shouldn't happen
|
||||
raise koji.GenericError, "No creation event found for %s in %s" % (nvr, tag_name)
|
||||
our_entry = entry
|
||||
if options.debug:
|
||||
print _histline(event_id, entry)
|
||||
print _histline(event_id, our_entry)
|
||||
#now go through the events since most recent creation entry
|
||||
timeline = timeline[i+1:]
|
||||
if not timeline:
|
||||
|
|
@ -1328,6 +1355,29 @@ def handle_prune_signed_copies(options, session, args):
|
|||
if options.debug:
|
||||
print "%s is latest in tag %s" % (nvr, tag_name)
|
||||
break
|
||||
#before we go any further, is this a protected tag?
|
||||
protect_tag = False
|
||||
for pattern in options.protect_tag:
|
||||
if fnmatch.fnmatch(tag_name, pattern):
|
||||
protect_tag = True
|
||||
break
|
||||
if protect_tag:
|
||||
# we use the same time limit as for the latest calculation
|
||||
# if this build was in this tag within that limit, then we will
|
||||
# not prune its signed copies
|
||||
if our_entry['revoke_event'] is None:
|
||||
#we're still tagged with a protected tag
|
||||
if options.debug:
|
||||
print "Build %s has protected tag %s" % (nvr, tag_name)
|
||||
is_protected = True
|
||||
break
|
||||
elif our_entry['revoke_ts'] > cutoff_ts:
|
||||
#we were still tagged here sometime before the cutoff
|
||||
if options.debug:
|
||||
print "Build %s had protected tag %s until %s" \
|
||||
% (nvr, tag_name, time.asctime(time.localtime(our_entry['revoke_ts'])))
|
||||
is_protected = True
|
||||
break
|
||||
replaced_ts = None
|
||||
revoke_ts = None
|
||||
others = {}
|
||||
|
|
@ -1406,6 +1456,8 @@ def handle_prune_signed_copies(options, session, args):
|
|||
break
|
||||
if is_latest:
|
||||
continue
|
||||
if is_protected:
|
||||
continue
|
||||
#not latest anywhere since cutoff, so we can remove all signed copies
|
||||
rpms = session.listRPMs(buildID=binfo['id'])
|
||||
session.multicall = True
|
||||
|
|
@ -2964,7 +3016,7 @@ def _printTaskInfo(session, task_id, level=0, recurse=True, verbose=True):
|
|||
files = session.listTaskOutput(task_id)
|
||||
logs = [filename for filename in files if filename.endswith('.log')]
|
||||
output = [filename for filename in files if not filename.endswith('.log')]
|
||||
files_dir = '%s/tasks/%i' % (koji.pathinfo.work(), task_id)
|
||||
files_dir = '%s/%s' % (koji.pathinfo.work(), koji.pathinfo.taskrelpath(task_id))
|
||||
|
||||
owner = session.getUser(info['owner'])['name']
|
||||
|
||||
|
|
|
|||
|
|
@ -4079,7 +4079,7 @@ class RootExports(object):
|
|||
given ID."""
|
||||
if '..' in fileName or '/' in fileName:
|
||||
raise koji.GenericError, 'Invalid file name: %s' % fileName
|
||||
filePath = '%s/tasks/%i/%s' % (koji.pathinfo.work(), taskID, fileName)
|
||||
filePath = '%s/%s/%s' % (koji.pathinfo.work(), koji.pathinfo.taskrelpath(taskID), fileName)
|
||||
filePath = os.path.normpath(filePath)
|
||||
if not os.path.isfile(filePath):
|
||||
raise koji.GenericError, 'no file "%s" output by task %i' % (fileName, taskID)
|
||||
|
|
@ -4103,7 +4103,7 @@ class RootExports(object):
|
|||
If stat is True, return a map of filename -> stat_info where stat_info
|
||||
is a map containing the values of the st_* attributes returned by
|
||||
os.stat()."""
|
||||
taskDir = '%s/tasks/%i' % (koji.pathinfo.work(), taskID)
|
||||
taskDir = '%s/%s' % (koji.pathinfo.work(), koji.pathinfo.taskrelpath(taskID))
|
||||
if os.path.isdir(taskDir):
|
||||
output = os.listdir(taskDir)
|
||||
if stat:
|
||||
|
|
|
|||
|
|
@ -630,10 +630,11 @@ def splice_rpm_sighdr(sighdr, src, dst=None, bufsize=8192):
|
|||
dst_fo.close()
|
||||
return dst
|
||||
|
||||
def get_rpm_header(f):
|
||||
def get_rpm_header(f, ts=None):
|
||||
"""Return the rpm header."""
|
||||
ts = rpm.TransactionSet()
|
||||
ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)
|
||||
if ts is None:
|
||||
ts = rpm.TransactionSet()
|
||||
ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)
|
||||
if isinstance(f, (str, unicode)):
|
||||
fo = file(f, "r")
|
||||
else:
|
||||
|
|
@ -1067,6 +1068,10 @@ class PathInfo(object):
|
|||
"""Return the directory where a repo belongs"""
|
||||
return self.topdir + ("/repos/%(tag_str)s/cache" % locals())
|
||||
|
||||
def taskrelpath(self, task_id):
|
||||
"""Return the relative path for the task work directory"""
|
||||
return "tasks/%s/%s" % (task_id % 10000, task_id)
|
||||
|
||||
def work(self):
|
||||
"""Return the work dir"""
|
||||
return self.topdir + '/work'
|
||||
|
|
@ -1588,7 +1593,10 @@ def taskLabel(taskInfo):
|
|||
if taskInfo.has_key('request'):
|
||||
build = taskInfo['request'][1]
|
||||
extra = buildLabel(build)
|
||||
elif method in ('newRepo', 'tagBuild', 'tagNotification'):
|
||||
elif method == 'newRepo':
|
||||
if taskInfo.has_key('request'):
|
||||
extra = str(taskInfo['request'][0])
|
||||
elif method in ('tagBuild', 'tagNotification'):
|
||||
# There is no displayable information included in the request
|
||||
# for these methods
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ class RepoManager(object):
|
|||
tags = {}
|
||||
for target in session.getBuildTargets():
|
||||
tag_id = target['build_tag']
|
||||
tags[tag_id] = 1
|
||||
tags[tag_id] = target['build_tag_name']
|
||||
#index repos by tag
|
||||
tag_repos = {}
|
||||
for repo in self.repos.values():
|
||||
|
|
@ -331,8 +331,8 @@ class RepoManager(object):
|
|||
if len(self.tasks) >= options.max_repo_tasks:
|
||||
self.logger.info("Maximum number of repo tasks reached.")
|
||||
break
|
||||
task_id = session.newRepo(tag_id)
|
||||
self.logger.info("Created newRepo task %s for tag %s" % (task_id, tag_id))
|
||||
task_id = session.newRepo(tags[tag_id])
|
||||
self.logger.info("Created newRepo task %s for tag %s (%s)" % (task_id, tag_id, tags[tag_id]))
|
||||
self.tasks[tag_id] = task_id
|
||||
#some cleanup
|
||||
n_deletes = 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue