fix merge conflicts

This commit is contained in:
Mike Bonnet 2008-11-25 16:56:56 -05:00
commit dbacf4c8e8
4 changed files with 170 additions and 66 deletions

View file

@ -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
View file

@ -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"

View file

@ -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())

View file

@ -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