1
0
mirror of https://github.com/openSUSE/osc.git synced 2025-01-12 16:56:15 +01:00

- add 'help' subcommand (and add help :-)

- make all subcommands functions -- so they can be used from outside (they
  still print directly their output; they could become iterators later)
- deprecate 'init' subcommand
- 0.5
This commit is contained in:
Dr. Peter Poeml 2006-05-23 13:48:58 +00:00
parent 6aac69f3cf
commit aa36c25505
5 changed files with 524 additions and 305 deletions

9
NEWS
View File

@ -1,3 +1,12 @@
0.5:
- help :-)
- fix status letter for files merged on update (in analogy to svn , it is
either G or U)
- if an old _files listing without any metadata is found, don't bother the user
with it
- make all subcommands properly importable functions
0.4:
- allow 'up' inside a project directory (will automatically pull in all new
packages). (For past checkouts, you may need to put the project name into

4
README
View File

@ -60,7 +60,7 @@ state, and conflicts are marked with special <<<<<<< and >>>>>>> lines.
After manually resolving the problem, use
osc resolved foo
Upload change content, this does only work within package directories, but not in project directories currently.
Upload change content
osc ci # current dir
osc ci <dir>
osc ci file1 file2 ...
@ -73,7 +73,7 @@ Show the status (which files have been changed locally)
Initialize a directory to be a working copy of an existing buildservice
package. (This is the same as checking out a package and then copying sources
into the directory. It does NOT create a new package.)
osc init <prj> <pac>
osc init <prj> <pac> # DEPRACATED
Mark files to be added or removed on the next 'checkin'
osc add file1 file2 ...

View File

@ -5,361 +5,572 @@
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
from core import *
def main():
cmd = sys.argv[1]
project = package = filename = None
# try:
# project = sys.argv[2]
# package = sys.argv[3]
# filename = sys.argv[4]
# except:
# pass
usage_general = """\
usage: osc <subcommand> [options] [args]
OpenSUSE build service command-line tool, version %s.
Type 'osc help <subcommand>' for help on a specific subcommand.
if cmd == 'init':
project = sys.argv[2]
package = sys.argv[3]
init_package_dir(project, package, os.path.curdir)
print 'Initializing %s (Project: %s, Package: %s)' % (os.curdir, project, package)
Most subcommands take file and/or directory arguments, recursing
on the directories. If no arguments are supplied to such a
command, it recurses on the current directory (inclusive) by default.
elif cmd == 'ls':
if len(sys.argv) == 2:
print '\n'.join(get_slash_source())
if len(sys.argv) == 3:
project = sys.argv[2]
print '\n'.join(meta_get_packagelist(project))
if len(sys.argv) == 4:
project = sys.argv[2]
package = sys.argv[3]
print '\n'.join(meta_get_filelist(project, package))
Available subcommands:
elif cmd == 'meta':
if len(sys.argv) == 4:
project = sys.argv[2]
package = sys.argv[3]
print ''.join(show_package_meta(project, package))
print ''.join(show_files_meta(project, package))
elif len(sys.argv) == 3:
project = sys.argv[2]
print ''.join(show_project_meta(project))
add
addremove
checkin (ci)
checkout (co)
diff
help
history (hist)
id
log
ls
meta
platforms
remove (del, delete, rm)
resolved
results
results_meta
status (st)
update (up)
elif cmd == 'diff':
args = parseargs()
pacs = findpacs(args)
for p in pacs:
if p.todo == []:
for i in p.filenamelist:
s = p.status(i)
if s == 'M' or s == 'C':
p.todo.append(i)
d = []
for filename in p.todo:
d.append('Index: %s\n' % filename)
d.append('===================================================================\n')
d.append(get_source_file_diff(p.dir, filename, p.rev))
if d:
print ''.join(d)
elif cmd == 'co' or cmd == 'checkout':
try:
project = sys.argv[2]
package = sys.argv[3]
filename = sys.argv[4]
except:
pass
if filename:
get_source_file(project, package, filename)
elif package:
checkout_package(project, package)
else:
# all packages
for package in meta_get_packagelist(project):
checkout_package(project, package)
""" % get_osc_version()
elif cmd == 'st' or cmd == 'status':
def init(args):
"""Initialize a directory to be a working copy of an existing buildservice
package. (This is the same as checking out a package and then copying sources
into the directory. It does NOT create a new package.)
args = parseargs()
pacs = findpacs(args)
usage: init <prj> <pac>
"""
for p in pacs:
# no files given as argument? Take all files in current dir
if not p.todo:
p.todo = p.filenamelist + p.filenamelist_unvers
for filename in p.todo:
s = p.status(filename)
if s == 'F':
print statfrmt('!', filename)
elif s != ' ':
print statfrmt(s, filename)
project = args[0]
package = args[1]
init_package_dir(project, package, os.path.curdir)
print 'Initializing %s (Project: %s, Package: %s)' % (os.curdir, project, package)
elif cmd == 'add':
if len(sys.argv) < 3:
print '%s requires at least one argument' % cmd
sys.exit(1)
def ls(args):
"""ls (list): List existing content on the server
filenames = parseargs()
usage: ls # list projects
ls Apache # list packages in a project
ls Apache subversion # list files of package of a project
"""
for filename in filenames:
if not os.path.exists(filename):
print "file '%s' does not exist" % filename
sys.exit(1)
pacs = findpacs(filenames)
for pac in pacs:
for filename in pac.todo:
if filename in exclude_stuff:
continue
pac.addfile(filename)
print statfrmt('A', filename)
if not args:
print '\n'.join(get_slash_source())
elif len(args) == 1:
project = args[0]
print '\n'.join(meta_get_packagelist(project))
elif len(args) == 2:
project = args[0]
package = args[1]
print '\n'.join(meta_get_filelist(project, package))
elif cmd == 'addremove':
args = parseargs()
pacs = findpacs(args)
for p in pacs:
def meta(args):
"""Shows meta information
p.todo = p.filenamelist + p.filenamelist_unvers
usage: meta Apache # show meta of project 'Apache'
meta Apache subversion # show meta of package 'subversion'
"""
for filename in p.todo:
if filename in exclude_stuff:
continue
state = p.status(filename)
if state == '?':
p.addfile(filename)
print statfrmt('A', filename)
elif state == '!':
p.put_on_deletelist(filename)
p.write_deletelist()
os.unlink(os.path.join(p.storedir, filename))
print statfrmt('D', filename)
if not args:
print 'missing argument'
print meta.func_doc
sys.exit(1)
if len(args) == 2:
project = args[0]
package = args[1]
print ''.join(show_package_meta(project, package))
print ''.join(show_files_meta(project, package))
elif len(args) == 1:
project = args[0]
print ''.join(show_project_meta(project))
def diff(args):
"""diff: Generates a diff, to view the local changes
usage: 1. osc diff # current dir
2. osc diff file1 file2 ...
elif cmd == 'ci' or cmd == 'checkin':
init_basicauth()
"""
args = parseargs()
args = parseargs(args)
pacs = findpacs(args)
pacs = findpacs(args)
for p in pacs:
p.todo = p.filenamelist_unvers + p.filenamelist
for filename in p.todo:
st = p.status(filename)
if st == 'A' or st == 'M':
p.todo_send.append(filename)
print 'Sending %s' % filename
elif st == 'D':
p.todo_delete.append(filename)
print 'Deleting %s' % filename
if not p.todo_send and not p.todo_delete:
print 'nothing to do for package %s' % p.name
continue
print 'Transmitting file data ',
for filename in p.todo_send:
put_source_file(p.prjname, p.name, os.path.join(p.dir, filename))
#copy_file(filename, os.path.join(store, filename))
for filename in p.todo_delete:
del_source_file(p.prjname, p.name, filename)
p.to_be_deleted.remove(filename)
p.update_filesmeta()
p.write_deletelist()
print
elif cmd == 'up' or cmd == 'update':
args = parseargs()
for arg in args:
# when 'update' is run inside a project dir, it should...
if is_project_dir(arg):
prj = Project(arg)
# (a) update all packages
for i in prj.pacs_have:
args.append(i)
# (b) fetch new packages
prj.checkout_missing_pacs()
args.remove(arg)
pacs = findpacs(args)
for p in pacs:
# save filelist and (modified) status before replacing the meta file
saved_filenames = p.filenamelist
saved_modifiedfiles = []
for p in pacs:
if p.todo == []:
for i in p.filenamelist:
if p.status(i) == 'M':
saved_modifiedfiles.append(i)
p.update_filesmeta()
p = Package(p.dir)
s = p.status(i)
if s == 'M' or s == 'C':
p.todo.append(i)
# which files do no longer exist upstream?
disappeared = []
for filename in saved_filenames:
if filename not in p.filenamelist:
disappeared.append(filename)
for filename in saved_filenames:
if filename in disappeared:
print statfrmt('D', filename)
p.delfile(filename)
continue
for filename in p.filenamelist:
state = p.status(filename)
if state == 'M' and filename in saved_modifiedfiles:
print 'merging'
status_after_merge = p.mergefile(filename)
print statfrmt(status_after_merge, filename)
elif state == 'M':
p.updatefile(filename)
print statfrmt('U', filename)
elif state == '!':
p.updatefile(filename)
print 'Restored \'%s\'' % filename
elif state == 'F':
p.updatefile(filename)
print statfrmt('A', filename)
elif state == ' ':
pass
p.update_pacmeta()
#print ljust(p.name, 45), 'At revision %s.' % p.rev
print 'At revision %s.' % p.rev
d = []
for filename in p.todo:
d.append('Index: %s\n' % filename)
d.append('===================================================================\n')
d.append(get_source_file_diff(p.dir, filename, p.rev))
if d:
print ''.join(d)
def checkout(args):
"""checkout (co): Check out content from the server.
elif cmd == 'rm' or cmd == 'delete':
if len(sys.argv) < 3:
print '%s requires at least one argument' % cmd
usage: co Apache # entire project
co Apache subversion # a package
co Apache subversion foo # single file -> to current dir
"""
project = package = filename = None
try:
project = args[0]
package = args[1]
filename = args[2]
except:
pass
if filename:
get_source_file(project, package, filename)
elif package:
checkout_package(project, package)
else:
# all packages
for package in meta_get_packagelist(project):
checkout_package(project, package)
def status(args):
"""Show the status (which files have been changed locally)
usage: st
st <directory>
st file1 file2 ...
"""
args = parseargs(args)
pacs = findpacs(args)
for p in pacs:
# no files given as argument? Take all files in current dir
if not p.todo:
p.todo = p.filenamelist + p.filenamelist_unvers
for filename in p.todo:
s = p.status(filename)
if s == 'F':
print statfrmt('!', filename)
elif s != ' ':
print statfrmt(s, filename)
def add(args):
"""Mark files to be added upon next 'checkin'
usage: add file1 file2 ...
"""
if not args:
print '%s requires at least one argument' % cmd
sys.exit(1)
filenames = parseargs(args)
for filename in filenames:
if not os.path.exists(filename):
print "file '%s' does not exist" % filename
sys.exit(1)
args = parseargs()
pacs = findpacs(args)
pacs = findpacs(filenames)
for p in pacs:
for pac in pacs:
for filename in pac.todo:
if filename in exclude_stuff:
continue
for filename in p.todo:
pac.addfile(filename)
print statfrmt('A', filename)
def addremove(args):
"""addremove: Adds all new files in local copy and removes all disappeared files.
usage: addremove
"""
args = parseargs(args)
pacs = findpacs(args)
for p in pacs:
p.todo = p.filenamelist + p.filenamelist_unvers
for filename in p.todo:
if filename in exclude_stuff:
continue
state = p.status(filename)
if state == '?':
p.addfile(filename)
print statfrmt('A', filename)
elif state == '!':
p.put_on_deletelist(filename)
p.write_deletelist()
try:
os.unlink(os.path.join(p.dir, filename))
os.unlink(os.path.join(p.storedir, filename))
except:
pass
os.unlink(os.path.join(p.storedir, filename))
print statfrmt('D', filename)
elif cmd == 'resolved':
if len(sys.argv) < 3:
print '%s requires at least one argument' % cmd
sys.exit(1)
args = parseargs()
pacs = findpacs(args)
def checkin(args):
"""checkin (ci): Upload change content from your working copy to the repository
for p in pacs:
usage: ci # current dir
ci <dir>
ci file1 file2 ...
"""
for filename in p.todo:
print "Resolved conflicted state of '%s'" % filename
p.clear_from_conflictlist(filename)
init_basicauth()
args = parseargs(args)
pacs = findpacs(args)
for p in pacs:
p.todo = p.filenamelist_unvers + p.filenamelist
for filename in p.todo:
st = p.status(filename)
if st == 'A' or st == 'M':
p.todo_send.append(filename)
print 'Sending %s' % filename
elif st == 'D':
p.todo_delete.append(filename)
print 'Deleting %s' % filename
if not p.todo_send and not p.todo_delete:
print 'nothing to do for package %s' % p.name
continue
print 'Transmitting file data ',
for filename in p.todo_send:
put_source_file(p.prjname, p.name, os.path.join(p.dir, filename))
#copy_file(filename, os.path.join(store, filename))
for filename in p.todo_delete:
del_source_file(p.prjname, p.name, filename)
p.to_be_deleted.remove(filename)
p.update_filesmeta()
p.write_deletelist()
print
elif cmd == 'id':
r = get_user_id(sys.argv[2])
if r:
print ''.join(r)
def update(args):
"""Update a working copy
usage: up
up [pac_dir] # update a single package by its path
up * # from within a project dir, update all packages
up # from within a project dir, update all packages
AND check out all newly added packages
"""
args = parseargs(args)
for arg in args:
# when 'update' is run inside a project dir, it should...
if is_project_dir(arg):
prj = Project(arg)
# (a) update all packages
for i in prj.pacs_have:
args.append(i)
# (b) fetch new packages
prj.checkout_missing_pacs()
args.remove(arg)
elif cmd == 'platforms':
if len(sys.argv) > 2:
project = sys.argv[2]
print '\n'.join(get_platforms_of_project(project))
else:
print '\n'.join(get_platforms())
pacs = findpacs(args)
for p in pacs:
elif cmd == 'results_meta':
wd = os.curdir
package = store_read_package(wd)
project = store_read_project(wd)
if len(sys.argv) > 2:
platform = sys.argv[2]
print ''.join(show_results_meta(project, package, platform))
else:
for platform in get_platforms_of_project(project):
print ''.join(show_results_meta(project, package, platform))
# save filelist and (modified) status before replacing the meta file
saved_filenames = p.filenamelist
saved_modifiedfiles = []
for i in p.filenamelist:
if p.status(i) == 'M':
saved_modifiedfiles.append(i)
p.update_filesmeta()
p = Package(p.dir)
elif cmd == 'results':
if len(sys.argv) > 3:
print 'getting results for more than one package is not supported'
print sys.exit(1)
# which files do no longer exist upstream?
disappeared = []
for filename in saved_filenames:
if filename not in p.filenamelist:
disappeared.append(filename)
if len(sys.argv) == 3:
wd = sys.argv[2]
else:
wd = os.curdir
package = store_read_package(wd)
project = store_read_project(wd)
for platform in get_platforms_of_project(project):
print '\n'.join(get_results(project, package, platform))
for filename in saved_filenames:
if filename in disappeared:
print statfrmt('D', filename)
p.delfile(filename)
continue
for filename in p.filenamelist:
state = p.status(filename)
if state == 'M' and filename in saved_modifiedfiles:
print 'merging'
status_after_merge = p.mergefile(filename)
print statfrmt(status_after_merge, filename)
elif state == 'M':
p.updatefile(filename)
print statfrmt('U', filename)
elif state == '!':
p.updatefile(filename)
print 'Restored \'%s\'' % filename
elif state == 'F':
p.updatefile(filename)
print statfrmt('A', filename)
elif state == ' ':
pass
p.update_pacmeta()
#print ljust(p.name, 45), 'At revision %s.' % p.rev
print 'At revision %s.' % p.rev
elif cmd == 'log':
wd = os.curdir
package = store_read_package(wd)
project = store_read_project(wd)
platform = sys.argv[2]
arch = sys.argv[3]
print ''.join(get_log(project, package, platform, arch))
elif cmd == 'hist' or cmd == 'history':
args = parseargs()
pacs = findpacs(args)
def delete(args):
"""rm (remove, del, delete): Mark files to be deleted upon next 'checkin'
for p in pacs:
print ''.join(get_history(p.prjname, p.name))
usage: rm file1 file2 ...
"""
if not args:
print 'delete requires at least one argument'
sys.exit(1)
args = parseargs(args)
pacs = findpacs(args)
for p in pacs:
for filename in p.todo:
p.put_on_deletelist(filename)
p.write_deletelist()
try:
os.unlink(os.path.join(p.dir, filename))
os.unlink(os.path.join(p.storedir, filename))
except:
pass
print statfrmt('D', filename)
def resolved(args):
"""If an update can't be merged automatically, a file is in 'C' (conflict)
state, and conflicts are marked with special <<<<<<< and >>>>>>> lines.
After manually resolving the problem, use
usage: resolved <filename>
"""
if not args:
print 'this command requires at least one argument'
sys.exit(1)
args = parseargs(args)
pacs = findpacs(args)
for p in pacs:
for filename in p.todo:
print "Resolved conflicted state of '%s'" % filename
p.clear_from_conflictlist(filename)
def userid(args):
"""id: show metadata about user <userid>
usage: id <userid>
"""
if not args:
print 'this command requires at least one argument'
sys.exit(1)
r = get_user_id(args[0])
if r:
print ''.join(r)
def platforms(args):
"""platforms: Shows platforms
usage 1. platforms
Shows available platforms/build targets
2. platforms <project>
Shows the configured platforms/build targets of a project
"""
if args:
project = args[0]
print '\n'.join(get_platforms_of_project(project))
else:
print "unknown command '%s'" % cmd
print '\n'.join(get_platforms())
def results_meta(args):
"""Shows the build results of the package in raw XML
usage: results_meta [platform]
"""
wd = os.curdir
package = store_read_package(wd)
project = store_read_project(wd)
if args:
platform = args[0]
print ''.join(show_results_meta(project, package, platform))
else:
for platform in get_platforms_of_project(project):
print ''.join(show_results_meta(project, package, platform))
def results(args):
"""Shows the build results of a package
usage: 1. results # package = current dir
2. results <packagedir>
"""
if args and len(args) > 1:
print 'getting results for more than one package is not supported'
print sys.exit(1)
if args:
wd = args[0]
else:
wd = os.curdir
package = store_read_package(wd)
project = store_read_project(wd)
for platform in get_platforms_of_project(project):
print '\n'.join(get_results(project, package, platform))
def log(args):
"""log: Shows the log file from a package (you need to be inside a package directory)
usage: log <platform> <arch>
"""
wd = os.curdir
package = store_read_package(wd)
project = store_read_project(wd)
platform = args[0]
arch = args[1]
print ''.join(get_log(project, package, platform, arch))
def history(args):
"""history: Shows the build history of a package (NOT IMPLEMENTED YET)
usage: history <pacdir>
"""
args = parseargs(args)
pacs = findpacs(args)
for p in pacs:
print ''.join(get_history(p.prjname, p.name))
def help(args):
"""help: Describe the usage of this program or its subcommands.
usage: help [SUBCOMMAND...]
"""
if args:
cmd = resolve_cmd_alias(args[0])
try:
print cmd_dict[cmd].func_doc
except KeyError:
print 'unknown command \'%s\'' % cmd
sys.exit(1)
else:
print usage_general
def resolve_cmd_alias(cmd):
if cmd == 'ci': return 'checkin'
if cmd == 'co': return 'checkout'
if cmd == 'st': return 'status'
if cmd == 'up': return 'update'
if cmd == 'list': return 'ls'
if cmd == 'hist': return 'history'
if cmd in ['del', 'remove', 'rm']: return 'delete'
return cmd
cmd_dict = {
'add': add,
'addremove': addremove,
'checkin': checkin,
'checkout': checkout,
'diff': diff,
'help': help,
'history': history,
'id': userid, # <- small difference here
'init': init, # depracated
'log': log,
'ls': ls,
'meta': meta,
'platforms': platforms,
'delete': delete,
'resolved': resolved,
'results': results,
'results_meta': results_meta,
'status': status,
'update': update,
}
def main():
"""handling of commandline arguments, and dispatching to subcommands"""
# which subcommand?
if len(sys.argv) < 2:
print "Type 'osc help' for usage."
sys.exit(0)
cmd = resolve_cmd_alias(sys.argv[1])
# more arguments?
if len(sys.argv) > 2:
args = sys.argv[2:]
else:
args = None
# run subcommand
cmd_dict[cmd](args)
if __name__ == '__main__':

View File

@ -5,7 +5,7 @@
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
__version__ = '0.4'
__version__ = '0.5'
import os
import sys
@ -375,12 +375,11 @@ def read_inconflict(dir):
return r
def parseargs():
if len(sys.argv) > 2:
args = sys.argv[2:]
def parseargs(list_of_args):
if list_of_args:
return list_of_args
else:
args = [ os.curdir ]
return args
return [ os.curdir ]
def filedir_to_pac(f):
@ -546,7 +545,7 @@ def check_store_version(dir):
sys.exit(1)
if v != __version__:
if v == '0.2' or v == '0.3':
if v == '0.2' or v == '0.3' or v == '0.4':
# version is fine, no migration needed
f = open(versionfile, 'w')
f.write(__version__ + '\n')

View File

@ -3,7 +3,7 @@
from distutils.core import setup
setup(name='osc',
version='0.4',
version='0.5',
description='opensuse commander',
author='Peter Poeml',
author_email='poeml@suse.de',