fix merge conflicts
This commit is contained in:
commit
dbacf4c8e8
4 changed files with 170 additions and 66 deletions
|
|
@ -986,6 +986,12 @@ class TaskManager(object):
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
# note: tasks are in priority order
|
# note: tasks are in priority order
|
||||||
self.logger.debug("task: %r" % task)
|
self.logger.debug("task: %r" % task)
|
||||||
|
if self.tasks.has_key(task['id']):
|
||||||
|
# we were running this task, but it apparently has been
|
||||||
|
# freed or reassigned. We can't do anything with it until
|
||||||
|
# updateTasks notices this and cleans up.
|
||||||
|
self.logger.debug("Task %(id)s freed or reassigned", task)
|
||||||
|
continue
|
||||||
if task['state'] == koji.TASK_STATES['ASSIGNED']:
|
if task['state'] == koji.TASK_STATES['ASSIGNED']:
|
||||||
self.logger.debug("task is assigned")
|
self.logger.debug("task is assigned")
|
||||||
if self.host_id == task['host_id']:
|
if self.host_id == task['host_id']:
|
||||||
|
|
|
||||||
141
cli/koji
141
cli/koji
|
|
@ -2050,6 +2050,8 @@ def anon_handle_list_tagged(options, session, args):
|
||||||
parser.add_option("--paths", action="store_true", help=_("Show the file paths"))
|
parser.add_option("--paths", action="store_true", help=_("Show the file paths"))
|
||||||
parser.add_option("--sigs", action="store_true", help=_("Show signatures"))
|
parser.add_option("--sigs", action="store_true", help=_("Show signatures"))
|
||||||
parser.add_option("--maven", action="store_true", help=_("Show Maven builds only"))
|
parser.add_option("--maven", action="store_true", help=_("Show Maven builds only"))
|
||||||
|
parser.add_option("--event", type='int', metavar="EVENT#", help=_("query at event"))
|
||||||
|
parser.add_option("--repo", type='int', metavar="REPO#", help=_("query at event for a repo"))
|
||||||
(options, args) = parser.parse_args(args)
|
(options, args) = parser.parse_args(args)
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
parser.error(_("A tag name must be specified"))
|
parser.error(_("A tag name must be specified"))
|
||||||
|
|
@ -2076,6 +2078,16 @@ def anon_handle_list_tagged(options, session, args):
|
||||||
options.rpms = True
|
options.rpms = True
|
||||||
if options.maven and not options.rpms:
|
if options.maven and not options.rpms:
|
||||||
opts['maven_only'] = True
|
opts['maven_only'] = True
|
||||||
|
if options.event is not None:
|
||||||
|
opts['event'] = options.event
|
||||||
|
if options.repo is not None:
|
||||||
|
repo = session.repoInfo(options.repo)
|
||||||
|
if not repo:
|
||||||
|
print "No such repo: %s" % options.repo
|
||||||
|
return
|
||||||
|
repo['timestr'] = time.asctime(time.localtime(repo['create_ts']))
|
||||||
|
print "Querying at event %(create_event)i (%(tag_name)s/%(timestr)s)" % repo
|
||||||
|
opts['event'] = repo['create_event']
|
||||||
|
|
||||||
if options.rpms:
|
if options.rpms:
|
||||||
rpms, builds = session.listTaggedRPMS(tag, **opts)
|
rpms, builds = session.listTaggedRPMS(tag, **opts)
|
||||||
|
|
@ -2491,6 +2503,14 @@ def anon_handle_rpminfo(options, session, args):
|
||||||
print "Payload: %(payloadhash)s" %info
|
print "Payload: %(payloadhash)s" %info
|
||||||
print "Size: %(size)s" %info
|
print "Size: %(size)s" %info
|
||||||
print "Build ID: %(build_id)s" %info
|
print "Build ID: %(build_id)s" %info
|
||||||
|
if info['buildroot_id'] is None:
|
||||||
|
print "No buildroot data available"
|
||||||
|
else:
|
||||||
|
br_info = session.getBuildroot(info['buildroot_id'])
|
||||||
|
print "Buildroot: %(id)i (tag %(tag_name)s, arch %(arch)s, repo %(repo_id)i)" % br_info
|
||||||
|
print "Build Host: %(host_name)s" % br_info
|
||||||
|
print "Build Task: %(task_id)i" % br_info
|
||||||
|
|
||||||
|
|
||||||
def anon_handle_buildinfo(options, session, args):
|
def anon_handle_buildinfo(options, session, args):
|
||||||
"Print basic information about a build"
|
"Print basic information about a build"
|
||||||
|
|
@ -3882,35 +3902,57 @@ def handle_set_pkg_owner_global(options, session, args):
|
||||||
parser = OptionParser(usage=usage)
|
parser = OptionParser(usage=usage)
|
||||||
parser.add_option("--verbose", action='store_true', help=_("List changes"))
|
parser.add_option("--verbose", action='store_true', help=_("List changes"))
|
||||||
parser.add_option("--test", action='store_true', help=_("Test mode"))
|
parser.add_option("--test", action='store_true', help=_("Test mode"))
|
||||||
|
parser.add_option("--old-user", "--from", action="store", help=_("Only change ownership for packages belonging to this user"))
|
||||||
(options, args) = parser.parse_args(args)
|
(options, args) = parser.parse_args(args)
|
||||||
if len(args) < 2:
|
if options.old_user:
|
||||||
|
if len(args) < 1:
|
||||||
|
parser.error(_("Please specify an owner"))
|
||||||
|
assert False
|
||||||
|
elif len(args) < 2:
|
||||||
parser.error(_("Please specify an owner and at least one package"))
|
parser.error(_("Please specify an owner and at least one package"))
|
||||||
assert False
|
assert False
|
||||||
activate_session(session)
|
activate_session(session)
|
||||||
owner = args[0]
|
owner = args[0]
|
||||||
|
packages = args[1:]
|
||||||
user = session.getUser(owner)
|
user = session.getUser(owner)
|
||||||
if not user:
|
if not user:
|
||||||
print "No such user: %s" % owner
|
print "No such user: %s" % owner
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
for package in args[1:]:
|
opts = {'with_dups' : True}
|
||||||
entries = session.listPackages(pkgID=package, with_dups=True)
|
old_user = None
|
||||||
|
if options.old_user:
|
||||||
|
old_user = session.getUser(options.old_user)
|
||||||
|
if not old_user:
|
||||||
|
print _("No such user: %s") % options.old_user
|
||||||
|
sys.exit(1)
|
||||||
|
opts['userID'] = old_user['id']
|
||||||
|
to_change = []
|
||||||
|
for package in packages:
|
||||||
|
entries = session.listPackages(pkgID=package, **opts)
|
||||||
if not entries:
|
if not entries:
|
||||||
print "No data for package %s" % package
|
print "No data for package %s" % package
|
||||||
continue
|
continue
|
||||||
for entry in entries:
|
to_change.extend(entries)
|
||||||
if user['id'] == entry['owner_id']:
|
if not packages and options.old_user:
|
||||||
if options.verbose:
|
entries = session.listPackages(**opts)
|
||||||
print "Preserving owner=%s for package %s in tag %s" \
|
if not entries:
|
||||||
% (user['name'], package, entry['tag_name'] )
|
print "No data for user %s" % old_user['name']
|
||||||
else:
|
sys.exit(1)
|
||||||
if options.test:
|
to_change.extend(entries)
|
||||||
print "Would have changed owner for %s in tag %s: %s -> %s" \
|
for entry in to_change:
|
||||||
% (package, entry['tag_name'], entry['owner_name'], user['name'])
|
if user['id'] == entry['owner_id']:
|
||||||
continue
|
if options.verbose:
|
||||||
if options.verbose:
|
print "Preserving owner=%s for package %s in tag %s" \
|
||||||
print "Changing owner for %s in tag %s: %s -> %s" \
|
% (user['name'], package, entry['tag_name'] )
|
||||||
% (package, entry['tag_name'], entry['owner_name'], user['name'])
|
else:
|
||||||
session.packageListSetOwner(entry['tag_id'], package, user['id'])
|
if options.test:
|
||||||
|
print "Would have changed owner for %s in tag %s: %s -> %s" \
|
||||||
|
% (entry['package_name'], entry['tag_name'], entry['owner_name'], user['name'])
|
||||||
|
continue
|
||||||
|
if options.verbose:
|
||||||
|
print "Changing owner for %s in tag %s: %s -> %s" \
|
||||||
|
% (entry['package_name'], entry['tag_name'], entry['owner_name'], user['name'])
|
||||||
|
session.packageListSetOwner(entry['tag_id'], entry['package_name'], user['id'])
|
||||||
|
|
||||||
def anon_handle_watch_task(options, session, args):
|
def anon_handle_watch_task(options, session, args):
|
||||||
"Track progress of particular tasks"
|
"Track progress of particular tasks"
|
||||||
|
|
@ -4042,7 +4084,7 @@ def handle_move_pkg(options, session, args):
|
||||||
if _running_in_bg() or options.nowait:
|
if _running_in_bg() or options.nowait:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
watch_tasks(session,tasks)
|
return watch_tasks(session, tasks)
|
||||||
|
|
||||||
def handle_untag_pkg(options, session, args):
|
def handle_untag_pkg(options, session, args):
|
||||||
"Remove a tag from one or more packages"
|
"Remove a tag from one or more packages"
|
||||||
|
|
@ -4050,22 +4092,69 @@ def handle_untag_pkg(options, session, args):
|
||||||
usage += _("\n(Specify the --help global option for a list of other help options)")
|
usage += _("\n(Specify the --help global option for a list of other help options)")
|
||||||
parser = OptionParser(usage=usage)
|
parser = OptionParser(usage=usage)
|
||||||
parser.add_option("--all", action="store_true", help=_("untag all versions of the package in this tag"))
|
parser.add_option("--all", action="store_true", help=_("untag all versions of the package in this tag"))
|
||||||
|
parser.add_option("--non-latest", action="store_true", help=_("untag all versions of the package in this tag except the latest"))
|
||||||
|
parser.add_option("-n", "--test", action="store_true", help=_("test mode"))
|
||||||
|
parser.add_option("-v", "--verbose", action="store_true", help=_("print details"))
|
||||||
parser.add_option("--force", action="store_true", help=_("force operation"))
|
parser.add_option("--force", action="store_true", help=_("force operation"))
|
||||||
(options, args) = parser.parse_args(args)
|
(options, args) = parser.parse_args(args)
|
||||||
if len(args) < 2:
|
if options.non_latest and options.force:
|
||||||
|
if len(args) < 1:
|
||||||
|
parser.error(_("Please specify a tag"))
|
||||||
|
assert False
|
||||||
|
elif len(args) < 2:
|
||||||
parser.error(_("This command takes at least two arguments: a tag name/ID and one or more package n-v-r's"))
|
parser.error(_("This command takes at least two arguments: a tag name/ID and one or more package n-v-r's"))
|
||||||
assert False
|
assert False
|
||||||
activate_session(session)
|
activate_session(session)
|
||||||
|
tag = session.getTag(args[0])
|
||||||
|
if not tag:
|
||||||
|
parser.error(_("Invalid tag: %s" % args[0]))
|
||||||
if options.all:
|
if options.all:
|
||||||
pkgs = []
|
builds = []
|
||||||
for pkg in args[1:]:
|
for pkg in args[1:]:
|
||||||
pkgs.extend([x['nvr'] for x in session.listTagged(args[0], package=pkg)])
|
builds.extend(session.listTagged(args[0], package=pkg))
|
||||||
|
elif options.non_latest:
|
||||||
|
if options.force and len(args) == 1:
|
||||||
|
tagged = session.listTagged(args[0])
|
||||||
|
else:
|
||||||
|
tagged = []
|
||||||
|
for pkg in args[1:]:
|
||||||
|
tagged.extend(session.listTagged(args[0], package=pkg))
|
||||||
|
# listTagged orders entries latest first
|
||||||
|
seen_pkg = {}
|
||||||
|
builds = []
|
||||||
|
for binfo in tagged:
|
||||||
|
if not seen_pkg.has_key(binfo['name']):
|
||||||
|
#latest for this package
|
||||||
|
if options.verbose:
|
||||||
|
print _("Leaving latest build for package %(name)s: %(nvr)s") % binfo
|
||||||
|
else:
|
||||||
|
builds.append(binfo)
|
||||||
|
seen_pkg[binfo['name']] = 1
|
||||||
else:
|
else:
|
||||||
pkgs = args[1:]
|
tagged = session.listTagged(args[0])
|
||||||
for pkg in pkgs:
|
idx = dict([(b['nvr'], b) for b in tagged])
|
||||||
print pkg
|
builds = []
|
||||||
#XXX trap errors
|
for nvr in args[1:]:
|
||||||
session.untagBuild(args[0], pkg, force=options.force)
|
binfo = idx.get(nvr)
|
||||||
|
if binfo:
|
||||||
|
builds.append(binfo)
|
||||||
|
else:
|
||||||
|
# not in tag, see if it even exists
|
||||||
|
binfo = session.getBuild(nvr)
|
||||||
|
if not binfo:
|
||||||
|
print _("No such build: %s") % nvr
|
||||||
|
else:
|
||||||
|
print _("Build %s not in tag %s") % (nvr, tag['name'])
|
||||||
|
if not options.force:
|
||||||
|
sys.exit(1)
|
||||||
|
builds.reverse()
|
||||||
|
for binfo in builds:
|
||||||
|
if options.test:
|
||||||
|
print _("would have untagged %(nvr)s") % binfo
|
||||||
|
else:
|
||||||
|
if options.verbose:
|
||||||
|
print _("untagging %(nvr)s") % binfo
|
||||||
|
session.untagBuild(tag['name'], binfo['nvr'], force=options.force)
|
||||||
|
|
||||||
def handle_unblock_pkg(options, session, args):
|
def handle_unblock_pkg(options, session, args):
|
||||||
"[admin] Unblock a package in the listing for tag"
|
"[admin] Unblock a package in the listing for tag"
|
||||||
|
|
|
||||||
|
|
@ -480,18 +480,6 @@ def eventCondition(event, table=None):
|
||||||
else:
|
else:
|
||||||
raise koji.GenericError, "Invalid event: %r" % event
|
raise koji.GenericError, "Invalid event: %r" % event
|
||||||
|
|
||||||
def get_last_event():
|
|
||||||
"""
|
|
||||||
Get the id and timestamp of the last event that modified the
|
|
||||||
system. Returns a map containing the following fields:
|
|
||||||
- id
|
|
||||||
- ts
|
|
||||||
"""
|
|
||||||
fields = ('id', 'ts')
|
|
||||||
q = """SELECT id, EXTRACT(EPOCH FROM time) FROM events
|
|
||||||
ORDER BY id DESC LIMIT 1"""
|
|
||||||
return _singleRow(q, {}, fields, strict=True)
|
|
||||||
|
|
||||||
def readGlobalInheritance(event=None):
|
def readGlobalInheritance(event=None):
|
||||||
c=context.cnx.cursor()
|
c=context.cnx.cursor()
|
||||||
fields = ('tag_id','parent_id','name','priority','maxdepth','intransitive',
|
fields = ('tag_id','parent_id','name','priority','maxdepth','intransitive',
|
||||||
|
|
@ -1061,13 +1049,10 @@ def readTaggedRPMS(tag, package=None, arch=None, event=None,inherit=False,latest
|
||||||
if isinstance(arch, basestring):
|
if isinstance(arch, basestring):
|
||||||
q += """AND rpminfo.arch = %(arch)s
|
q += """AND rpminfo.arch = %(arch)s
|
||||||
"""
|
"""
|
||||||
|
elif isinstance(arch, (list, tuple)):
|
||||||
|
q += """AND rpminfo.arch IN %(arch)s\n"""
|
||||||
else:
|
else:
|
||||||
try:
|
raise koji.GenericError, 'invalid arch option: %s' % arch
|
||||||
it = iter(arch)
|
|
||||||
except TypeError:
|
|
||||||
raise koji.GenericError, 'invalid arch option: %s' % arch
|
|
||||||
q += """AND rpminfo.arch in (%s)
|
|
||||||
""" % ','.join(["'%s'" % a for a in it])
|
|
||||||
|
|
||||||
# unique constraints ensure that each of these queries will not report
|
# unique constraints ensure that each of these queries will not report
|
||||||
# duplicate rpminfo entries, BUT since we make the query multiple times,
|
# duplicate rpminfo entries, BUT since we make the query multiple times,
|
||||||
|
|
@ -2601,8 +2586,10 @@ def get_build(buildInfo, strict=False):
|
||||||
owner_id: ID of the user who kicked off the build
|
owner_id: ID of the user who kicked off the build
|
||||||
owner_name: name of the user who kicked off the build
|
owner_name: name of the user who kicked off the build
|
||||||
creation_event_id: id of the create_event
|
creation_event_id: id of the create_event
|
||||||
creation_time: time the build was created
|
creation_time: time the build was created (text)
|
||||||
|
creation_ts: time the build was created (epoch)
|
||||||
completion_time: time the build was completed (may be null)
|
completion_time: time the build was completed (may be null)
|
||||||
|
completion_ts: time the build was completed (epoch, may be null)
|
||||||
|
|
||||||
If there is no build matching the buildInfo given, and strict is specified,
|
If there is no build matching the buildInfo given, and strict is specified,
|
||||||
raise an error. Otherwise return None.
|
raise an error. Otherwise return None.
|
||||||
|
|
@ -2619,6 +2606,8 @@ def get_build(buildInfo, strict=False):
|
||||||
('build.task_id', 'task_id'), ('events.id', 'creation_event_id'), ('events.time', 'creation_time'),
|
('build.task_id', 'task_id'), ('events.id', 'creation_event_id'), ('events.time', 'creation_time'),
|
||||||
('package.id', 'package_id'), ('package.name', 'package_name'), ('package.name', 'name'),
|
('package.id', 'package_id'), ('package.name', 'package_name'), ('package.name', 'name'),
|
||||||
("package.name || '-' || build.version || '-' || build.release", 'nvr'),
|
("package.name || '-' || build.version || '-' || build.release", 'nvr'),
|
||||||
|
('EXTRACT(EPOCH FROM events.time)','creation_ts'),
|
||||||
|
('EXTRACT(EPOCH FROM build.completion_time)','completion_ts'),
|
||||||
('users.id', 'owner_id'), ('users.name', 'owner_name'))
|
('users.id', 'owner_id'), ('users.name', 'owner_name'))
|
||||||
query = """SELECT %s
|
query = """SELECT %s
|
||||||
FROM build
|
FROM build
|
||||||
|
|
@ -5197,7 +5186,28 @@ class RootExports(object):
|
||||||
context.session.assertPerm('admin')
|
context.session.assertPerm('admin')
|
||||||
return "%r" % context.opts
|
return "%r" % context.opts
|
||||||
|
|
||||||
getLastEvent = staticmethod(get_last_event)
|
def getLastEvent(self, before=None):
|
||||||
|
"""
|
||||||
|
Get the id and timestamp of the last event recorded in the system.
|
||||||
|
Events are usually created as the result of a configuration change
|
||||||
|
in the database.
|
||||||
|
|
||||||
|
If "before" (int or float) is specified, return the last event
|
||||||
|
that occurred before that time (in seconds since the epoch).
|
||||||
|
If there is no event before the given time, an error will be raised.
|
||||||
|
"""
|
||||||
|
fields = ('id', 'ts')
|
||||||
|
values = {}
|
||||||
|
q = """SELECT id, EXTRACT(EPOCH FROM time) FROM events"""
|
||||||
|
if before is not None:
|
||||||
|
if not isinstance(before, (int, long, float)):
|
||||||
|
raise koji.GenericError, 'invalid type for before: %s' % type(before)
|
||||||
|
# use the repr() conversion because it retains more precision than the
|
||||||
|
# string conversion
|
||||||
|
q += """ WHERE EXTRACT(EPOCH FROM time) < %(before)r"""
|
||||||
|
values['before'] = before
|
||||||
|
q += """ ORDER BY id DESC LIMIT 1"""
|
||||||
|
return _singleRow(q, values, fields, strict=True)
|
||||||
|
|
||||||
def makeTask(self,*args,**opts):
|
def makeTask(self,*args,**opts):
|
||||||
#this is mainly for debugging
|
#this is mainly for debugging
|
||||||
|
|
@ -6093,7 +6103,10 @@ class RootExports(object):
|
||||||
"""Grant a permission to a user"""
|
"""Grant a permission to a user"""
|
||||||
context.session.assertPerm('admin')
|
context.session.assertPerm('admin')
|
||||||
user_id = get_user(userinfo,strict=True)['id']
|
user_id = get_user(userinfo,strict=True)['id']
|
||||||
perm_id = get_perm_id(permission,strict=True)
|
perm = lookup_perm(permission, strict=True)
|
||||||
|
perm_id = perm['id']
|
||||||
|
if perm['name'] in koji.auth.get_user_perms(user_id):
|
||||||
|
raise koji.GenericError, 'user %s already has permission: %s' % (userinfo, perm['name'])
|
||||||
insert = """INSERT INTO user_perms (user_id, perm_id)
|
insert = """INSERT INTO user_perms (user_id, perm_id)
|
||||||
VALUES (%(user_id)i, %(perm_id)i)"""
|
VALUES (%(user_id)i, %(perm_id)i)"""
|
||||||
_dml(insert, locals())
|
_dml(insert, locals())
|
||||||
|
|
|
||||||
34
util/kojira
34
util/kojira
|
|
@ -119,8 +119,21 @@ class ManagedRepo(object):
|
||||||
|
|
||||||
def tryDelete(self):
|
def tryDelete(self):
|
||||||
"""Remove the repo from disk, if possible"""
|
"""Remove the repo from disk, if possible"""
|
||||||
#we check just the event age first since it is faster
|
tag_info = session.getTag(self.tag_id)
|
||||||
age = time.time() - self.event_ts
|
if not tag_info:
|
||||||
|
self.logger.warn('Could not get info for tag %i, skipping delete of repo %i' %
|
||||||
|
(self.tag_id, self.repo_id))
|
||||||
|
return False
|
||||||
|
tag_name = tag_info['name']
|
||||||
|
path = pathinfo.repo(self.repo_id, tag_name)
|
||||||
|
try:
|
||||||
|
#also check dir age. We do this because a repo can be created from an older event
|
||||||
|
#and should not be removed based solely on that event's timestamp.
|
||||||
|
mtime = os.stat(path).st_mtime
|
||||||
|
except OSError:
|
||||||
|
self.logger.error("Can't stat repo directory: %s" % path)
|
||||||
|
return True
|
||||||
|
age = time.time() - max(self.event_ts, mtime)
|
||||||
if age < options.deleted_repo_lifetime:
|
if age < options.deleted_repo_lifetime:
|
||||||
#XXX should really be called expired_repo_lifetime
|
#XXX should really be called expired_repo_lifetime
|
||||||
return False
|
return False
|
||||||
|
|
@ -133,23 +146,6 @@ class ManagedRepo(object):
|
||||||
return False
|
return False
|
||||||
self.logger.info("Deleted repo %s" % self.repo_id)
|
self.logger.info("Deleted repo %s" % self.repo_id)
|
||||||
self.state = koji.REPO_DELETED
|
self.state = koji.REPO_DELETED
|
||||||
tag_info = session.getTag(self.tag_id)
|
|
||||||
if not tag_info:
|
|
||||||
self.logger.warn('Could not get info for tag %i, skipping delete of repo %i' %
|
|
||||||
(self.tag_id, self.repo_id))
|
|
||||||
return False
|
|
||||||
tag_name = tag_info['name']
|
|
||||||
path = pathinfo.repo(self.repo_id, tag_name)
|
|
||||||
#also check dir age. We do this because a repo can be created from an older event
|
|
||||||
#and should not be removed based solely on that event's timestamp.
|
|
||||||
try:
|
|
||||||
age = time.time() - os.stat(path).st_mtime
|
|
||||||
except OSError:
|
|
||||||
self.logger.error("Can't stat repo directory: %s" % path)
|
|
||||||
return True
|
|
||||||
if age < options.deleted_repo_lifetime:
|
|
||||||
#XXX should really be called expired_repo_lifetime
|
|
||||||
return False
|
|
||||||
safe_rmtree(path, strict=False)
|
safe_rmtree(path, strict=False)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue