[Zope3-checkins] CVS: Zope3/src/zope/fssync - fssync.py:1.9 main.py:1.4
Guido van Rossum
guido@python.org
Tue, 13 May 2003 15:16:59 -0400
Update of /cvs-repository/Zope3/src/zope/fssync
In directory cvs.zope.org:/tmp/cvs-serv30438
Modified Files:
fssync.py main.py
Log Message:
Towards more rational command line handling.
=== Zope3/src/zope/fssync/fssync.py 1.8 => 1.9 ===
--- Zope3/src/zope/fssync/fssync.py:1.8 Tue May 13 13:32:50 2003
+++ Zope3/src/zope/fssync/fssync.py Tue May 13 15:16:58 2003
@@ -39,6 +39,8 @@
from zope.fssync.metadata import Metadata
from zope.fssync.merger import Merger
+unwanted = ("", os.curdir, os.pardir)
+
class Error(Exception):
"""User-level error, e.g. non-existent file.
@@ -133,7 +135,6 @@
If no root url is found, return None.
"""
- unwanted = ("", os.curdir, os.pardir)
dir = realpath(target)
while dir:
zopedir = join(dir, "@@Zope")
@@ -307,22 +308,31 @@
if exists(target) and not isdir(target):
raise Error("target should be a directory", target)
self.ensuredir(target)
- fp, headers = self.network.httpreq(rootpath,
- "@@toFS.zip?writeOriginals=False")
+ fp, headers = self.network.httpreq(rootpath, "@@toFS.zip")
try:
self.merge_zipfile(fp, target)
finally:
fp.close()
self.network.saverooturl(target)
+ def multiple(self, args, method):
+ if not args:
+ args = [os.curdir]
+ for target in args:
+ if self.metadata.getentry(target):
+ method(target)
+ else:
+ names = self.metadata.getnames(target)
+ if not names:
+ method(target) # Will raise an exception
+ else:
+ for name in names:
+ method(join(target, name))
+
def commit(self, target):
entry = self.metadata.getentry(target)
if not entry:
- names = self.metadata.getnames(target)
- if len(names) != 1:
- raise Error("can only commit a single directory")
- target = join(target, names[0])
- entry = self.metadata.getentry(target)
+ raise Error("nothing known about", target)
self.network.loadrooturl(target)
path = entry["path"]
zipfile = tempfile.mktemp(".zip")
@@ -353,16 +363,11 @@
def update(self, target):
entry = self.metadata.getentry(target)
if not entry:
- names = self.metadata.getnames(target)
- if len(names) != 1:
- raise Error("can only commit a single directory")
- target = join(target, names[0])
- entry = self.metadata.getentry(target)
+ raise Error("nothing known about", target)
self.network.loadrooturl(target)
head, tail = split(realpath(target))
path = entry["path"]
- fp, headers = self.network.httpreq(path,
- "@@toFS.zip?writeOriginals=False")
+ fp, headers = self.network.httpreq(path, "@@toFS.zip")
try:
self.merge_zipfile(fp, head)
finally:
@@ -397,8 +402,7 @@
if entry:
raise Error("path '%s' is already registered", path)
head, tail = split(path)
- unwanted = ("", os.curdir, os.pardir)
- if tail in unwanted:
+ if tail in unwanted or not head:
path = realpath(path)
head, tail = split(path)
if head == path or tail in unwanted:
@@ -416,8 +420,6 @@
entry["flag"] = "added"
if isdir(path):
entry["type"] = "zope.app.content.folder.Folder"
- self.ensuredir(join(path, "@@Zope"))
- self.dumpentries({}, path)
else:
# XXX Need to guess better based on extension
entry["type"] = "zope.app.content.file.File"
@@ -426,6 +428,9 @@
self.metadata.flush()
def merge_dirs(self, localdir, remotedir):
+ if not isdir(remotedir):
+ return
+
self.ensuredir(localdir)
ldirs, lnondirs = classifyContents(localdir)
=== Zope3/src/zope/fssync/main.py 1.3 => 1.4 ===
--- Zope3/src/zope/fssync/main.py:1.3 Tue May 13 11:28:03 2003
+++ Zope3/src/zope/fssync/main.py Tue May 13 15:16:59 2003
@@ -12,20 +12,18 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""New fssync utility.
-
-Connects to the database using HTTP (using the toFS.zip view for
-checkout and update and the fromFS.form view for commit).
-
-An attempt is made to make the behavior similar to that of cvs.
+"""Filesystem synchronization utility for Zope 3.
Command line syntax summary:
-fssync checkout URL TARGETDIR
-fssync update [FILE_OR_DIR ...]
-fssync status [FILE_OR_DIR ...]
-fssync commit [FILE_OR_DIR ...]
-fssync diff [FILE_OR_DIR ...]
+fssync [global_options] checkout [options] URL [TARGETDIR]
+fssync [global_options] update [options] [TARGET ...]
+fssync [global_options] commit [options] [TARGET ...]
+fssync [global_options] diff [options] [TARGET ...]
+fssync [global_options] status [options] [TARGET ...]
+
+For now, the only global option is -h/--help; there are no local
+options yet.
$Id$
"""
@@ -44,74 +42,104 @@
# Hack to fix the module search path
try:
- import zope.xmlpickle
+ import zope.fssync
# All is well
except ImportError:
# Fix the path to include <root>/src
srcdir = join(rootdir, "src")
sys.path.append(srcdir)
-from zope.xmlpickle import loads, dumps
-
from zope.fssync.fssync import Error, FSSync
class Usage(Error):
"""Subclass for usage error (command-line syntax).
- This should set an exit status of 2 rather than 1.
+ You should return an exit status of 2 rather than 1 when catching this.
"""
def main(argv=None):
+ """Main program.
+
+ You can pass it an argument list (which must include the command
+ name as argv[0]); it defaults to sys.argv.
+
+ The return value is the suggested sys.exit() status code:
+ 0 or None for success
+ 2 for command line syntax errors
+ 1 or other for later errors
+ """
try:
if argv is None:
argv = sys.argv
- # XXX getopt
- args = argv[1:]
+
+ try:
+ opts, args = getopt.getopt(argv[1:], "h", ["help"])
+ except getopt.error, msg:
+ raise Usage("global option error: %s", msg)
+
+ for o, a in opts:
+ if o in ("-h", "--help"):
+ print __doc__
+ return 0
+
command = args[0]
- # XXX more getopt
- args = args[1:]
- if command in ("checkout", "co"):
- url, fspath = args
- checkout(url, fspath)
- elif command in ("update", "up"):
- args = args or [os.curdir]
- for fspath in args:
- print "update(%r)" % fspath
- update(fspath)
- elif command in ("commit", "com"):
- args = args or [os.curdir]
- [fspath] = args
- commit(fspath)
- elif command == "add":
- add(args)
- else:
- raise Usage("command %r not recognized" % command)
+ if command not in command_table:
+ hits = []
+ for c in command_table:
+ if c.startswith(command):
+ hits.append(c)
+ if not hits:
+ raise Usage("unrecognized command", command)
+ if len(hits) > 1:
+ raise Usage("ambiguous command abbreviation %r (%s)",
+ command, "|".join(hits))
+ command = hits[0]
+
+ short_opts, long_opts, handler = command_table[command]
+
+ try:
+ opts, args = getopt.getopt(args[1:], short_opts, long_opts)
+ except getopt.error, msg:
+ raise Usage("%s option error: %s", command, msg)
+
+ return handler(opts, args)
+
except Usage, msg:
- print msg
- print "for help use --help"
+ print >>sys.stderr, msg
+ print >>sys.stderr, "for help use --help"
return 2
+
except Error, msg:
- print msg
+ print >>sys.stderr, msg
return 1
+
else:
return None
-def checkout(rooturl, target):
+def checkout(opts, args):
+ rooturl, target = args
fs = FSSync(rooturl=rooturl)
fs.checkout(target)
-def commit(target):
+def commit(opts, args):
fs = FSSync()
- fs.commit(target)
+ fs.multiple(args, fs.commit)
-def update(target):
+def update(opts, args):
fs = FSSync()
- fs.update(target)
+ fs.multiple(args, fs.update)
-def add(args):
- fs = FSSync(os.curdir)
+def add(opts, args):
+ fs = FSSync()
for a in args:
fs.add(a)
+
+command_table = {
+ "checkout": ("", [], checkout),
+ "update": ("", [], update),
+ "commit": ("", [], commit),
+ "add": ("", [], add),
+ }
if __name__ == "__main__":
sys.exit(main(sys.argv))