[Zope3-checkins] CVS: Zope3/utilities/fssync - README.txt:1.2 add.py:1.2 checkout.py:1.2 commit.py:1.2 common.py:1.2 diff.py:1.2 sync.py:1.2 update.py:1.2 usage.py:1.2
Guido van Rossum
guido@python.org
Mon, 5 May 2003 14:01:05 -0400
Update of /cvs-repository/Zope3/utilities/fssync
In directory cvs.zope.org:/tmp/cvs-serv2527/utilities/fssync
Added Files:
README.txt add.py checkout.py commit.py common.py diff.py
sync.py update.py usage.py
Log Message:
Merge fssync stuff back to trunk. A few things actually work (I
successfully did a checkout of some files and diffed them; though
commit doesn't seem to work yet), and you know how I love long-living
branches....
=== Zope3/utilities/fssync/README.txt 1.1 => 1.2 ===
--- /dev/null Mon May 5 14:01:04 2003
+++ Zope3/utilities/fssync/README.txt Mon May 5 14:01:03 2003
@@ -0,0 +1,16 @@
+Filesystem synchronization
+--------------------------
+
+This directory contains a utility (sync.py) and the modules it uses
+that implement filesystem synchronization. This is a little like CVS,
+with the Data.fs service as the repository.
+
+Jim Fulton's original proposal explains the theory and background:
+
+ http://dev.zope.org/Wikis/DevSite/Projects/ComponentArchitecture/
+ FileSystemSynchronizationProposal
+
+The command line syntax of the utility is given in usage.py.
+
+The implementation was originally written by Jim Fulton and ZeOmega's
+deb_h. It is now maintained by Guido van Rossum.
=== Zope3/utilities/fssync/add.py 1.1 => 1.2 ===
--- /dev/null Mon May 5 14:01:04 2003
+++ Zope3/utilities/fssync/add.py Mon May 5 14:01:03 2003
@@ -0,0 +1,176 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import string, os
+
+from common import getZODBPath, getApplicationRoot, getObject
+from common import getObjectAdapter, setPrint, IObjectDirectory
+from zope.app.fssync.classes import FSAddRequest
+from zope.component import getView, queryView
+from zope.app.content.folder import Folder
+from zope.app.fssync.syncer import toFS, fromFS
+from zope.xmlpickle.xmlpickle import loads
+
+from zope.component.view import viewService
+
+
+env = os.environ
+
+def add(fspath
+ , dbpath
+ , siteconfpath
+ , newobjecttype
+ , newobjectname):
+
+ """Adds objects to File system
+
+ Creates an object in the file system based on the object type
+ passed with -t option.
+ """
+ fspath = os.path.abspath(fspath)
+ if not os.path.isdir(fspath):
+ return 'sync [add aborted] : %s is not a directory' %(fspath)
+
+ if not os.path.exists(os.path.join(fspath, '@@Zope')):
+ return 'sync [add aborted] : @@Zope administrative folder not found in %s' \
+ %(fspath)
+
+ objpath = getZODBPath(fspath)
+ root = getApplicationRoot(dbpath, siteconfpath)
+ container = getObject(objpath, root)
+ if container is None:
+ container, name, path = getObject(objpath, root, 'Y')
+ fsroot = os.path.abspath(fspath[:string.find(fspath, objpath)])
+ location = os.path.abspath(os.path.join(fsroot, path[1:]))
+ fromFS(container, name, location, 'T')
+
+ container = getObject(objpath, root)
+
+ adapter = getObjectAdapter(container)
+
+ if newobjecttype:
+ newobjecttype = '.'+newobjecttype
+ for file in newobjectname:
+ entries_path = os.path.join(os.path.join(fspath, os.path.dirname(file)),'@@Zope','Entries.xml')
+ entries = {}
+ if os.path.exists(entries_path):
+ entries = loads(open(entries_path).read())
+ if getObject(objpath+'/'+file, root) is not None:
+ setPrint('Object already exist in the ZODB : %s' \
+ %(os.path.join(fspath,file)))
+ elif entries.has_key(os.path.basename(file)):
+ setPrint('Object already exist in sandbox : %s' \
+ %(os.path.join(fspath,file)))
+ else:
+ err = addObject(adapter, fspath, newobjecttype, file, objpath)
+ if err is not None:
+ setPrint(err)
+ break
+ else:
+ for file in newobjectname:
+ entries_path = os.path.join(os.path.join(fspath, os.path.dirname(file)),'@@Zope','Entries.xml')
+ entries = {}
+ if os.path.exists(entries_path):
+ entries = loads(open(entries_path).read())
+ if getObject(objpath+'/'+file, root) is not None:
+ setPrint('Object already exist in the ZODB : %s' \
+ %(os.path.join(fspath,file)))
+ elif entries.has_key(os.path.basename(file)):
+ setPrint('Object already exist in sandbox : %s' \
+ %(os.path.join(fspath,file)))
+ else:
+ newobjecttype = '.'+string.split(file,'.')[-1]
+ err = addObject(adapter
+ , fspath
+ , newobjecttype
+ , file
+ , objpath)
+ if err is not None:
+ setPrint(err)
+ return None
+
+def addObject(adapter
+ , fspath
+ , newobjecttype
+ , newobjectname
+ , objpath):
+
+ mode = 'N'
+ if IObjectDirectory.isImplementedBy(adapter):
+ request = FSAddRequest()
+ view = queryView(adapter, newobjecttype, request)
+ if view is not None:
+ newobjectpath = os.path.abspath(os.path.join(fspath, newobjectname))
+ if not os.path.exists(os.path.dirname(newobjectpath)):
+ return 'Nothing known about : %s'%(newobjectpath)
+ newobject = view.create()
+ objpath = objpath+'/'+newobjectname
+ objectname = os.path.basename(newobjectpath)
+ newobjectpath = os.path.dirname(newobjectpath)
+ dir_list = createAdminFolder(newobjectpath, objpath)
+ keys = dir_list.keys()
+ keys.sort()
+ for sl_no in keys:
+ ob = Folder()
+ toFS(ob, dir_list[sl_no][2], dir_list[sl_no][0], mode, dir_list[sl_no][1])
+ toFS(newobject, objectname, newobjectpath, mode, objpath)
+ else:
+ newobjectpath = os.path.abspath(os.path.join(fspath, newobjectname))
+ if not os.path.exists(newobjectpath):
+ return 'Nothing known about : %s'%(newobjectpath)
+ view = getView(adapter, '.', request)
+ newobject = view.create(newobjectpath)
+ objpath = os.path.abspath(objpath+'/'+newobjectname)
+ objectname = os.path.basename(newobjectpath)
+ newobjectpath = os.path.dirname(newobjectpath)
+ path_list = string.split(newobjectname, os.sep)
+ if len(path_list) > 1:
+ if path_list[-1] != objectname:
+ return 'Nothing known about : %s'%(path_list[-1])
+
+ dir_list = createAdminFolder(newobjectpath, objpath)
+ keys = dir_list.keys()
+ keys.sort()
+ for sl_no in keys:
+ ob = Folder()
+ toFS(ob, dir_list[sl_no][2], dir_list[sl_no][0], mode, dir_list[sl_no][1])
+ toFS(newobject, objectname, newobjectpath, mode, objpath)
+
+ else:
+ return 'Not a container type : %s' %(os.path.basename(fspath))
+ return None
+
+def createAdminFolder(fspath, objpath, name=None, data={}):
+ if name is not None:
+ data[len(string.split(objpath, '/'))] = (fspath, objpath, name)
+ if not os.path.exists(os.path.join(fspath, '@@Zope')):
+ return createAdminFolder(os.path.dirname(fspath), os.path.dirname(objpath), os.path.basename(fspath))
+ return data
+
+def addTypes(dbpath
+ , siteconfpath):
+ root = getApplicationRoot(dbpath, siteconfpath)
+ f = Folder()
+ adapter = getObjectAdapter(f)
+ request = FSAddRequest()
+ allviews = viewService.all()['default']
+ setPrint("\nALL AVAILABLE TYPES")
+ setPrint("====================================================\n")
+ for view in allviews:
+ try:
+ if len(view)>1 and view[0] == '.':
+ doc = getView(adapter, view, request).__doc__
+ setPrint(' %s \n %s \n\n' % (view, doc))
+ except:
+ pass
=== Zope3/utilities/fssync/checkout.py 1.1 => 1.2 ===
--- /dev/null Mon May 5 14:01:04 2003
+++ Zope3/utilities/fssync/checkout.py Mon May 5 14:01:03 2003
@@ -0,0 +1,70 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import string, os
+
+from zope.app.fssync.syncer import toFS
+
+from common import getObject, getApplicationRoot
+from common import makeNewEntry, getObjectAdapter
+
+def checkout(fspath
+ , dbpath
+ , siteconfpath
+ , objpath):
+ """Checks out objects from ZODB to the file system
+
+ Downloads ZODB objects in file system to the specified path
+ specified but -f option.
+ """
+ sandbox_path = fspath
+ if not os.path.isabs(objpath):
+ objpath = '/'+objpath
+ objpath = os.path.abspath(objpath)
+ root = getApplicationRoot(dbpath, siteconfpath)
+ main_ob = getObject(objpath, root)
+ ob_name = os.path.basename(objpath)
+ if main_ob is not None:
+ path = ''
+ for dir in string.split(objpath[:string.rfind(objpath,ob_name)], '/')[1:-1]:
+ path = os.path.join(path,dir)
+ sandbox_path = os.path.join(fspath, path)
+ admin_dir = os.path.join(os.path.dirname(sandbox_path), '@@Zope')
+ entries_path = os.path.join(os.path.dirname(sandbox_path),
+ '@@Zope'
+ , 'Entries.xml')
+ if not os.path.exists(sandbox_path):
+ os.mkdir(sandbox_path)
+ if not os.path.exists(admin_dir):
+ os.mkdir(admin_dir)
+ if not os.path.exists(entries_path):
+ makeNewEntry(admin_dir)
+
+ o_path = '/'+path
+ ob = getObject(o_path, root)
+ adapter = getObjectAdapter(ob)
+ type = adapter.typeIdentifier()
+ factory = adapter.factory()
+ name = os.path.basename(o_path)
+ makeNewEntry(admin_dir
+ , name
+ , type
+ , factory
+ , o_path)
+
+ fspath = sandbox_path
+ toFS(main_ob, ob_name, fspath)
+ return None
+ else:
+ return "Invalid object path"
=== Zope3/utilities/fssync/commit.py 1.1 => 1.2 ===
--- /dev/null Mon May 5 14:01:04 2003
+++ Zope3/utilities/fssync/commit.py Mon May 5 14:01:03 2003
@@ -0,0 +1,155 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import os, string, commands
+
+from zope.app.fssync.syncer import fromFS
+from common import getZODBPath, createTempfile, getObject
+from common import getApplicationRoot, traverseFS, checkConflictData
+from common import isNewObject, setPrint
+from transaction import get_transaction
+
+env = os.environ
+
+def commit(fspath
+ , dbpath
+ , siteconfpath
+ , mode=None):
+ """Checks in from file system to ZODB
+
+ Saves the unconflict files in ZODB as Zope objects from the
+ file system.
+ """
+ fspath = os.path.abspath(fspath)
+ vpath = '<>'
+ if os.path.isdir(fspath):
+ admin_dir = os.path.join(fspath,'@@Zope')
+ else:
+ admin_dir = os.path.join(os.path.dirname(fspath),'@@Zope')
+ if not os.path.exists(admin_dir):
+ return 'sync [commit aborted] : @@Zope administrative folder not found'
+
+ root = getApplicationRoot(dbpath, siteconfpath)
+ if mode == 'F':
+ err = doCommit(fspath, root, mode)
+ if err is not None:
+ return err
+ else:
+ mapping_paths = traverseFS(fspath, {})
+ for sandbox_path in mapping_paths.keys():
+ original_path = string.strip(mapping_paths[sandbox_path][0])
+ zopedb_path = string.strip(mapping_paths[sandbox_path][1])
+ if isNewObject(sandbox_path):
+ fsroot = os.path.abspath(sandbox_path[:string.find(sandbox_path
+ , zopedb_path)])
+ path = ''
+ for object in string.split(zopedb_path,'/')[1:]:
+ path = os.path.join(path,object)
+ newobjpath = os.path.join(fsroot,path)
+ if isNewObject(newobjpath):
+ err = doCommit(newobjpath, root, 'F')
+ if err is not None:
+ return err
+ if os.path.isdir(newobjpath):
+ vpath = newobjpath
+ break
+ else:
+ if string.find(sandbox_path,vpath)==-1:
+ fmt_sandbox_path = ''
+ fmt_original_path = ''
+ for dir in string.split(sandbox_path,os.sep):
+ if string.find(dir, ' ')<>-1:
+ fmt_sandbox_path = os.path.join(fmt_sandbox_path
+ , '\''+dir+'\'')
+ else:
+ fmt_sandbox_path = os.path.join(fmt_sandbox_path
+ , dir)
+
+ for dir in string.split(original_path,os.sep):
+ if string.find(dir, ' ')<>-1:
+ fmt_original_path = os.path.join(fmt_original_path
+ , '\''+dir+'\'')
+ else:
+ fmt_original_path = os.path.join(fmt_original_path
+ , dir)
+ fmt_sandbox_path = os.sep + fmt_sandbox_path
+ fmt_original_path = os.sep + fmt_original_path
+
+ ob = getObject(zopedb_path, root)
+ zopedb_temp_file = createTempfile(ob, zopedb_path)
+ diff_cmd1 = """diff -q -b %s %s;echo $?""" \
+ %(fmt_original_path, zopedb_temp_file)
+ diff_res1 = commands.getoutput(diff_cmd1)
+ isConflict = int(diff_res1[-1])
+ diff_cmd2 = """diff -q -b %s %s;echo $?""" \
+ %(fmt_sandbox_path, fmt_original_path)
+ diff_res2 = commands.getoutput(diff_cmd2)
+ isCommitRequired = int(diff_res2[-1])
+
+ if checkConflictData(sandbox_path, zopedb_path):
+ isConflict = 1
+ if isConflict:
+ msg = "%s Conflict, Uptodate checkin failed" \
+ %(zopedb_path)
+ setPrint(msg)
+ else:
+ if not (isCommitRequired == isConflict == 0):
+ msg = "%s <-- %s" \
+ %(zopedb_path, string.split(zopedb_path,'/')[-1])
+ err = doCommit(sandbox_path, root)
+ if err is not None:
+ return err
+ setPrint(msg)
+
+ if os.path.exists(zopedb_temp_file):
+ os.remove(zopedb_temp_file)
+
+ return None
+
+
+def doCommit(fspath, root, mode=None):
+ container = ''
+ objpath = getZODBPath(fspath)
+ objname = string.split(objpath, '/')[-1]
+ path = string.split(objpath, '/')[:-1]
+
+ for item in path:
+ if item:
+ container = container +'[\''+item+'\']'
+ try:
+ if container:
+ container=eval('root'+container)
+ else:
+ container=root
+ except:
+ return 'sync [commit aborted] : invalid object path --- %s' \
+ %(objpath)
+
+ #copying to ZODB
+ fromFS(container, objname , os.path.dirname(fspath), mode)
+ get_transaction().commit()
+
+ if mode is None:
+ #copying to original
+ f = open(fspath, 'r')
+ data = f.read()
+ f.close()
+ original_path = os.path.join(os.path.dirname(fspath)
+ ,'@@Zope'
+ ,'Original'
+ ,os.path.basename(fspath))
+ f = open(original_path, 'w')
+ f.write(string.strip(data))
+ f.close()
+ return None
=== Zope3/utilities/fssync/common.py 1.1 => 1.2 ===
--- /dev/null Mon May 5 14:01:04 2003
+++ Zope3/utilities/fssync/common.py Mon May 5 14:01:03 2003
@@ -0,0 +1,287 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import os, tempfile, string
+
+from zope.app.fssync.fsregistry import getSynchronizer
+from zope.app.fssync.syncer import toFS
+from zope.app import Application
+from zope.app.interfaces.dublincore import IZopeDublinCore
+from zope.app.interfaces.fssync import IObjectEntry
+from zope.app.interfaces.fssync import IObjectFile, IObjectDirectory
+from zope.app.traversing import traverse, getPath
+from zope.component import queryAdapter, getService
+from zope.exceptions import NotFoundError
+from zope.xmlpickle.xmlpickle import dumps, loads
+
+seperator = os.sep
+
+def getObjectAdapter(ob):
+ """Returns the object adapter.
+ """
+ syncService = getService(ob, 'FSRegistryService')
+ adapter = syncService.getSynchronizer(ob)
+ return adapter
+
+def getApplicationRoot(dbpath
+ , siteconfpath):
+ """Returns the application root.
+ """
+ app = Application(dbpath, siteconfpath)
+ root = app()
+ return root
+
+def getObject(objpath
+ , root
+ , prev=None
+ , name=None):
+ """Gets the object from ZODB.
+ """
+ if prev is None:
+ try:
+ ob = traverse(root,objpath)
+ return ob
+ except:
+ return None
+ else:
+ try:
+ ob = traverse(root,objpath)
+ return ob , name, objpath
+ except:
+ return (getObject(os.path.dirname(objpath)
+ , root
+ , 'Y'
+ , os.path.basename(objpath)), name, objpath)[0]
+
+def getNewObject(ob
+ , folders
+ , files):
+ """Returns the entire tree of a ZODB object.
+ """
+ adapter = getObjectAdapter(ob)
+ path = ''
+ try:
+ path = str(getPath(ob))
+ except TypeError:
+ pass
+
+ if IObjectFile.isImplementedBy(adapter):
+ files.append(path)
+ else:
+ folders.append(path)
+ for cname, cob in adapter.contents():
+ getNewObject(cob, folders, files)
+ return folders, files
+
+def getZODBPath(targetfile
+ , key=None):
+ """Returns the physical path of an object in the ZODB
+ of a filesysten representation.
+ """
+ targetfile = os.path.abspath(targetfile)
+ entries_path = os.path.join(os.path.dirname(targetfile)
+ ,'@@Zope'
+ ,'Entries.xml')
+ entries = loads(open(entries_path).read())
+ if key is None:
+ objectpath = entries[os.path.basename(targetfile)]['path']
+ else:
+ try:
+ objectpath = entries[os.path.basename(targetfile)][key]
+ except:
+ return None
+ return objectpath
+
+def isNewObject(targetfile):
+ """Determines if the object in the File-system is new.
+ """
+ targetfile = os.path.abspath(targetfile)
+ entries_path = os.path.join(os.path.dirname(targetfile)
+ ,'@@Zope'
+ ,'Entries.xml')
+ entries = loads(open(entries_path).read())
+ if entries[os.path.basename(targetfile)].has_key('isNew'):
+ return 1
+ else:
+ return 0
+
+def getObjectData(ob):
+ """Returns the data of a ZODB object.
+ """
+ adapter = adapter = getObjectAdapter(ob)
+ objectdata = adapter.getBody()
+ return objectdata
+
+def getObjectDataTempfile(targetfile
+ , objpath
+ , dbpath
+ , siteconfpath):
+ """Returns the data of a particular object in ZODB.
+ """
+ root = getApplicationRoot(dbpath, siteconfpath)
+ objectpath = getZODBPath(targetfile)
+ ob = getObject(objectpath, root)
+ adapter = adapter = getObjectAdapter(ob)
+ dublincore_adapter = queryAdapter(ob, IZopeDublinCore)
+ modification_date = dublincore_adapter.ModificationDate()
+ object_data = adapter.getBody()
+ temp_file = tempfile.mktemp('tmp')
+ fo = open(temp_file,'w')
+ fo.write(string.strip(object_data))
+ fo.close()
+ return temp_file, objectpath, modification_date
+
+
+def createTempfile(ob
+ , objectpath):
+ """Creates a temporaty file in the File-system.
+ """
+ objectdata = getObjectData(ob)
+ temp_file = tempfile.mktemp('tmp')
+ fo = open(temp_file,'w')
+ fo.write(string.strip(objectdata))
+ fo.close()
+ return temp_file
+
+def checkFSPath(pathlist):
+ """Checks the file system path.
+ """
+ for path in pathlist:
+ if not os.path.exists(path):
+ err = "Invalid file system path --- "+str(path)
+ elif not os.access(path,2):
+ err = "Permission denied on --- "+str(path)
+ else:
+ err = None
+ if err is not None:
+ return err
+
+def mapFS(mappings
+ , root
+ , objectroot
+ , fsroot):
+ """Returns the new object list in the zopedb which
+ are not available in the File-system.
+ """
+ ob = getObject(objectroot, root)
+ folders, files = getNewObject(ob, [], [])
+ for folder in folders:
+ path = fsroot
+ for part in string.split(folder, '/'):
+ path = os.path.join(path, part)
+ if not os.path.exists(path):
+ location = os.path.dirname(path)
+ ob = getObject(folder, root)
+ ob_name = string.split(folder, '/')[-1]
+ toFS(ob, ob_name, location)
+ for file in files:
+ path = fsroot
+ for part in string.split(file, '/'):
+ path = os.path.join(path, part)
+ if not os.path.exists(path):
+ location = os.path.dirname(path)
+ ob = getObject(file, root)
+ ob_name = string.split(file, '/')[-1]
+ toFS(ob, ob_name, location)
+
+def traverseFS(fspath
+ , mapping_paths):
+ """Traverse through the File-system.
+ """
+ if os.path.isdir(fspath):
+ root=fspath
+ dirlist=os.listdir(root)
+ for item in dirlist:
+ if item!='@@Zope':
+ fspath=os.path.join(root,item)
+ if os.path.isdir(fspath):
+ traverseFS(fspath, mapping_paths)
+ else:
+ sandbox_path = fspath
+ original_path = os.path.join(os.path.dirname(fspath)
+ , '@@Zope'
+ , 'Original'
+ , os.path.basename(fspath))
+ if os.path.exists(original_path):
+ zopedb_path = getZODBPath(fspath)
+ mapping_paths[sandbox_path] = [original_path
+ , zopedb_path]
+ else:
+ sandbox_path = fspath
+ original_path = os.path.join(os.path.dirname(fspath)
+ , '@@Zope'
+ , 'Original'
+ , os.path.basename(fspath))
+ if os.path.exists(original_path):
+ zopedb_path = getZODBPath(fspath)
+ mapping_paths[sandbox_path] = [original_path
+ , zopedb_path]
+
+ return mapping_paths
+
+def checkConflictData(sandbox_path
+ , zopedb_path):
+ """Checks for conflict data in the File-system.
+ """
+ isConflict = 0
+ f = open(sandbox_path,'r')
+ data = f.read()
+ f.close()
+ filter1 = '<<<<<<< %s' % (sandbox_path)
+ filter2 = '>>>>>>> %s' % (zopedb_path)
+ if string.find(data, filter1)<>-1 and string.find(data, filter2)<>-1:
+ isConflict = 1
+ else:
+ isConflict = 0
+
+ return isConflict
+
+
+def makeNewEntry(admin_dir
+ , name=None
+ , type=None
+ , factory=None
+ , objpath=None
+ , isNew=None):
+ """Edits the Entries.xml file.
+ """
+ entries = {}
+ entries_path = os.path.join(admin_dir, 'Entries.xml')
+ if os.path.exists(entries_path):
+ entries = loads(open(entries_path).read())
+ if not entries.has_key(name) and name is not None:
+ if isNew:
+ entries[name] = {'type': type
+ , 'factory': factory
+ , 'isNew': 'Y'
+ , 'path': objpath}
+ else:
+ entries[name] = {'type': type
+ , 'factory': factory
+ , 'path': objpath}
+ open(entries_path, 'w').write(dumps(entries))
+
+def getFSRoot(fspath
+ , next=None):
+ """Returns the sandbox root.
+ """
+ fspath = os.path.abspath(fspath)
+ if not os.path.exists(os.path.join(fspath,'@@Zope')):
+ return os.path.join(fspath,next)
+ else:
+ return getFSRoot(os.path.dirname(fspath)
+ , os.path.basename(fspath))
+
+def setPrint(output_string):
+ print output_string
=== Zope3/utilities/fssync/diff.py 1.1 => 1.2 ===
--- /dev/null Mon May 5 14:01:04 2003
+++ Zope3/utilities/fssync/diff.py Mon May 5 14:01:03 2003
@@ -0,0 +1,141 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+from common import getObjectDataTempfile, setPrint
+import os, commands, calendar, string
+
+def getdiff(targetfile
+ , objpath
+ , dbpath
+ , siteconfpath
+ , diffoption=None):
+ """Returns the difference between two files
+
+ Gets the diff between :
+ -- Current in Sandbox and Original of last sync
+ -- Current in Sandbox and Current in ZODB
+ -- Current in ZODB and Original of last sync.
+ """
+ temp_file = ''
+ objectpath = ''
+ modification_date = None
+ zodbtargetfile = targetfile
+ if not os.path.isabs(targetfile):
+ targetfile=os.path.join(os.path.abspath(os.curdir)
+ ,targetfile)
+ if not os.path.exists(targetfile):
+ return "sync [diff aborted] : Target file does not exist --- %s" \
+ % (str(targetfile))
+ if os.path.isdir(targetfile):
+ return "sync [diff aborted] : Target file found to be a directory --- %s" \
+ % (str(targetfile))
+ if not os.path.exists(os.path.join(os.path.abspath(os.path.dirname(targetfile))
+ ,'@@Zope')):
+ return 'sync [diff aborted] : @@Zope administrative folder not found'
+
+ if string.find(os.path.basename(targetfile), ' ')<>-1:
+ targetfile = os.path.join(os.path.dirname(targetfile)
+ , '\''+os.path.basename(targetfile)+'\'')
+
+ if diffoption == '-1':
+ from_file = os.path.join(os.path.dirname(targetfile)
+ ,'@@Zope'
+ ,'Original')
+ to_file = targetfile
+ elif diffoption == '-2':
+ temp_file, objectpath, modification_date = getObjectDataTempfile(zodbtargetfile
+ , objpath
+ , dbpath
+ , siteconfpath)
+ from_file = targetfile
+ to_file = temp_file
+ elif diffoption == '-3':
+ temp_file, objectpath, modification_date = getObjectDataTempfile(zodbtargetfile
+ , objpath
+ , dbpath
+ , siteconfpath)
+ from_file = os.path.join(os.path.dirname(targetfile)
+ ,'@@Zope'
+ ,'Original'
+ ,os.path.basename(targetfile))
+ to_file = temp_file
+
+ diff_cmd ="""diff -a -b -B -c %s %s""" \
+ % (from_file,to_file)
+ diff_res = commands.getoutput(diff_cmd)
+ diff_res = setOutput(diff_res
+ , temp_file
+ , objectpath
+ , modification_date)
+ setPrint(diff_res)
+
+ if temp_file:
+ os.remove(temp_file)
+
+ return None
+
+def getDiffDate(strdt):
+ """Returns date in Day Mon DD hh:mm:ss YYYY format.
+ """
+ fmt_date=''
+ if strdt:
+ strdt = str(strdt)
+ weekdays={0:'Mon'
+ ,1:'Tue'
+ ,2:'Wed'
+ ,3:'Thu'
+ ,4:'Fri'
+ ,5:'Sat'
+ ,6:'Sun'}
+ months={1:'Jan'
+ , 2:'Feb'
+ , 3:'Mar'
+ , 4:'Apr'
+ , 5:'May'
+ , 6:'Jun'
+ , 7:'Jul'
+ , 8:'Aug'
+ , 9:'Sep'
+ , 10:'Oct'
+ , 11:'Nov'
+ , 12:'Dec'}
+ date=string.split(string.split(strdt,'T')[0],'-')
+ time=string.split(string.split(strdt,'T')[1],'.')[0]
+ day=weekdays[calendar.weekday(int(date[0])
+ ,int(date[1])
+ ,int(date[2]))]
+ fmt_date=day+' '+months[int(date[1])]+' '+date[2]+' '+time+' '+date[0]
+
+ return fmt_date
+
+def setOutput(diff_res
+ , temp_file
+ , objectpath
+ , modification_date):
+ """Sets the diff output replacing it with original object
+ path and modification datetime.
+ """
+ changed_line = ''
+ modification_date = getDiffDate(modification_date)
+ if temp_file:
+ for line in string.split(diff_res,'\n'):
+ if string.find(line,temp_file)<>-1:
+ changed_line = line
+ break
+ if changed_line:
+ newline = changed_line[:string.find(changed_line,temp_file)]
+ newline = newline + objectpath+'\t\t'+modification_date
+ diff_res = string.replace(diff_res, changed_line, newline)
+
+ return "\n\n"+diff_res+"\n\n"
=== Zope3/utilities/fssync/sync.py 1.1 => 1.2 ===
--- /dev/null Mon May 5 14:01:04 2003
+++ Zope3/utilities/fssync/sync.py Mon May 5 14:01:03 2003
@@ -0,0 +1,199 @@
+#!/usr/bin/env python
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import sys, string, getopt, os, commands
+
+# Hack to fix the module search path
+try:
+ import zope.app
+ # All is well
+except ImportError:
+ # Fix the path, assuming this script is <root>/utilities/fssync/sync.py
+ # and the zope module is <root>/src/zope/.
+ _script = sys.argv[0]
+ _scriptdir = os.path.abspath(os.path.dirname(_script))
+ _rootdir = os.path.dirname(os.path.dirname(_scriptdir))
+ _srcdir = os.path.join(_rootdir, "src")
+ sys.path.append(_srcdir)
+
+from diff import getdiff
+from common import checkFSPath, setPrint
+from checkout import checkout
+from commit import commit
+from update import update
+from usage import USAGE
+from add import add, addTypes
+
+def main(argv):
+ short_options = ':f:o:d:s:1:2:3:t:'
+ long_options = ['fspath='
+ , 'objpath='
+ , 'dbpath='
+ , 'siteconfpath=']
+
+ operations = ['commit'
+ , 'checkout'
+ , 'update'
+ , 'diff'
+ , 'fcommit'
+ , 'add'
+ , 'addtypes']
+
+ err = ""
+
+ usage = USAGE % argv[0]
+
+ try:
+ optlist, args = getopt.getopt(sys.argv[1:]
+ , short_options
+ , long_options)
+
+ env=os.environ
+
+ objpath = ''
+ operation = ''
+ targetfile = ''
+ diffoption = '-1'
+ newobjectname = ''
+ newobjecttype = ''
+
+ if env.has_key('SYNCROOT'): fspath = env['SYNCROOT']
+ else: fspath = '.'
+ if env.has_key('ZODBPATH'): dbpath = env['ZODBPATH']
+ else: dbpath = '../../../Data.fs'
+ if env.has_key('SITECONFPATH'): siteconfpath = env['SITECONFPATH']
+ else: siteconfpath = '../../../site.zcml'
+
+ if len(optlist) > 0 or len(args) > 0:
+ for opt in optlist:
+ if (opt[0] == '-f') or (opt[0] == '--fspath'):
+ fspath = opt[1]
+ elif (opt[0] == '-o') or (opt[0] == '--objpath'):
+ objpath = opt[1]
+ elif (opt[0] == '-d') or (opt[0] == '--dbpath'):
+ dbpath = opt[1]
+ elif (opt[0] == '-s') or (opt[0] == '--siteconfpath'):
+ siteconfpath = opt[1]
+ elif (opt[0] == '-1' or opt[0] == '-2' or opt[0] == '-3'):
+ diffoption = opt[0]
+ targetfile = opt[1]
+ elif opt[0] == '-t':
+ newobjecttype = opt[1]
+
+ newobjectname = args[1:]
+
+ if len(args) <1:
+ err = "No operation has been specified"
+ raise err
+ elif args[0] != 'add' and len(args) >1:
+ err = "CommandlineError"
+ raise err
+ elif args[0] not in operations:
+ err = "Invalid operation---"+str(args[0])
+ raise err
+ else:
+ operation = args[0]
+
+ fspath, dbpath, siteconfpath = (os.path.abspath(fspath)
+ , os.path.abspath(dbpath)
+ , os.path.abspath(siteconfpath))
+ path=[fspath, dbpath, siteconfpath]
+ err=checkFSPath(path)
+ if err is not None:
+ raise err
+
+ else:
+ if len(args)>1:
+ if args[1]=='diff':
+ targetfile = args[0]
+ operation = args[1]
+ else:
+ setPrint(usage)
+ sys.exit(1)
+ else:
+ setPrint(usage)
+ sys.exit(1)
+
+ #Calls the specified operation
+ err = operate(operation
+ , fspath
+ , dbpath
+ , siteconfpath
+ , objpath
+ , targetfile
+ , diffoption
+ , newobjecttype
+ , newobjectname)
+ if err is not None:
+ raise err
+
+ except err:
+ setPrint(err)
+ sys.exit(1)
+
+
+
+
+def operate(operation
+ , fspath
+ , dbpath
+ , siteconfpath
+ , objpath
+ , targetfile
+ , diffoption
+ , newobjecttype
+ , newobjectname):
+ """Operates based on the operations passed
+ """
+ err=""
+ if operation == 'checkout':
+ err = checkout(fspath
+ , dbpath
+ , siteconfpath
+ , objpath)
+ elif operation == 'commit':
+ err = commit(fspath
+ , dbpath
+ , siteconfpath)
+ elif operation == 'update':
+ err = update(fspath
+ , dbpath
+ , siteconfpath)
+ elif operation == 'diff':
+ err = getdiff(targetfile
+ , objpath
+ , dbpath
+ , siteconfpath
+ , diffoption)
+ elif operation == 'fcommit':
+ err = commit(fspath
+ , dbpath
+ , siteconfpath
+ , 'F')
+ elif operation == 'add':
+ err = add(fspath
+ , dbpath
+ , siteconfpath
+ , newobjecttype
+ , newobjectname)
+ elif operation == 'addtypes':
+ err = addTypes(dbpath
+ , siteconfpath)
+
+ return err
+
+
+# If called from the command line
+if __name__=='__main__': main(sys.argv)
=== Zope3/utilities/fssync/update.py 1.1 => 1.2 ===
--- /dev/null Mon May 5 14:01:04 2003
+++ Zope3/utilities/fssync/update.py Mon May 5 14:01:03 2003
@@ -0,0 +1,156 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+import string, os, commands
+
+from common import getZODBPath, createTempfile, getObject
+from common import mapFS, traverseFS, checkConflictData, getApplicationRoot
+from common import isNewObject, getFSRoot, setPrint
+
+from zope.app.fssync.syncer import toFS
+
+env = os.environ
+
+def update(fspath
+ , dbpath
+ , siteconfpath):
+ """Updates the checked out objects in the file system from a ZODB
+
+ updates the files in the sandbox based on the file system path given
+ by -f option.
+ """
+ root = getApplicationRoot(dbpath, siteconfpath)
+ if env.has_key('SYNCROOT'):
+ if os.path.abspath(fspath) == os.path.abspath(env['SYNCROOT']):
+ if os.path.isdir(os.path.abspath(fspath)):
+ module_list = os.listdir(os.path.abspath(fspath))
+ if '@@Zope' in module_list:
+ module_list.remove('@@Zope')
+ for module in module_list:
+ fspath = os.path.join(fspath, module)
+ updateSettings(fspath, root)
+ else:
+ return 'sync [update aborted] : @@Zope administrative folder not found in %s' \
+ %(fspath)
+ else:
+ updateSettings(fspath, root)
+ else:
+ updateSettings(fspath, root)
+
+def updateSettings(fspath, root):
+ """does the settings for update
+ """
+ fspath = os.path.abspath(fspath)
+ if os.path.isdir(fspath):
+ admin_dir = os.path.join(fspath,'@@Zope')
+ else:
+ admin_dir = os.path.join(os.path.dirname(fspath),'@@Zope')
+ if not os.path.exists(admin_dir):
+ return 'sync [update aborted] : @@Zope administrative folder not found in %s'\
+ %(fspath)
+
+ mappings = {}
+ mapping_paths = {}
+ mapping_paths.update(traverseFS(fspath, mapping_paths))
+
+ for sandbox_path in mapping_paths.keys():
+ original_path = string.strip(mapping_paths[sandbox_path][0])
+ zopedb_path = string.strip(mapping_paths[sandbox_path][1])
+ if checkConflictData(sandbox_path, zopedb_path):
+ setPrint('C %s'%(zopedb_path[1:]))
+ else:
+ if not isNewObject(sandbox_path):
+ mappings[zopedb_path] = sandbox_path
+
+ fmt_sandbox_path = ''
+ fmt_original_path = ''
+ for dir in string.split(sandbox_path,os.sep):
+ if string.find(dir, ' ')<>-1:
+ fmt_sandbox_path = os.path.join(fmt_sandbox_path, '\''+dir+'\'')
+ else:
+ fmt_sandbox_path = os.path.join(fmt_sandbox_path, dir)
+
+ for dir in string.split(original_path,os.sep):
+ if string.find(dir, ' ')<>-1:
+ fmt_original_path = os.path.join(fmt_original_path, '\''+dir+'\'')
+ else:
+ fmt_original_path = os.path.join(fmt_original_path, dir)
+ fmt_sandbox_path = os.sep + fmt_sandbox_path
+ fmt_original_path = os.sep + fmt_original_path
+
+ ob = getObject(zopedb_path, root)
+ zopedb_temp_file = createTempfile(ob, zopedb_path)
+ diff3_cmd = """diff3 -a %s %s %s""" %(fmt_sandbox_path
+ , fmt_original_path
+ , zopedb_temp_file)
+ diff3_res = commands.getoutput(diff3_cmd)
+ if len(string.strip(diff3_res))>1:
+ diffverify=string.strip(diff3_res[0:5])
+ if diffverify=='====1':
+ setPrint('M %s'%(zopedb_path[1:]))
+ elif diffverify=='====2':
+ doUpdate('C', ob, zopedb_path, sandbox_path)
+ setPrint('M %s'%(zopedb_path[1:]))
+ elif diffverify=='====3':
+ doUpdate('U', ob, zopedb_path, sandbox_path)
+ elif diffverify=='====':
+ diff3_cmd = """diff3 -a -m %s %s %s;echo $?""" %(fmt_sandbox_path
+ , fmt_original_path
+ , zopedb_temp_file)
+ diff3_res = commands.getoutput(diff3_cmd)
+ diff3_res = string.replace(diff3_res
+ , zopedb_temp_file
+ , zopedb_path)
+ if diff3_res[-1]=='0':
+ setPrint('Merging changes in %s' \
+ %(zopedb_path[1:]))
+ else:
+ setPrint('C Merging changes in %s' \
+ %(zopedb_path[1:]))
+
+ f = open(sandbox_path, 'w')
+ f.write(string.strip(diff3_res[:-1]))
+ f.close()
+ doUpdate('C'
+ , ob
+ , zopedb_path
+ , sandbox_path)
+
+ if os.path.exists(zopedb_temp_file):
+ os.remove(zopedb_temp_file)
+
+ if os.path.isdir(fspath):
+ objectroot = getZODBPath(fspath)
+ fsroot = getFSRoot(fspath)
+ mapFS(mappings
+ , root
+ , objectroot
+ , fsroot)
+
+
+
+def doUpdate(mode
+ , ob
+ , zopedb_path
+ , sandbox_path):
+ """Updates data
+ """
+ sandbox_path = os.path.dirname(sandbox_path)
+ ob_name = string.split(zopedb_path,'/')[-1]
+ if mode=='U':
+ if ob is not None:
+ toFS(ob, ob_name, sandbox_path)
+ elif mode=='C':
+ if ob is not None:
+ toFS(ob, ob_name, sandbox_path, mode)
=== Zope3/utilities/fssync/usage.py 1.1 => 1.2 ===
--- /dev/null Mon May 5 14:01:04 2003
+++ Zope3/utilities/fssync/usage.py Mon May 5 14:01:03 2003
@@ -0,0 +1,231 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+USAGE="""
+
+Usage: %s [options] operation
+
+The available options are:
+
+-f / --fspath=
+Set the file system path where the object is to be dumped.
+Is used with all the operation.
+
+-o / --objpath=
+Looks up for the Object in the specified path in the ZODB.
+Is used with checkout operation.
+
+-d / --dbpath=
+The path of ZODB.
+Is used with all the operation.
+
+-s / --siteconfpath=
+The path for site.zcml.
+Is used with all the operation.
+
+-t / --type=
+The type of object to be added to the file system.
+Is used with add operation.
+
+OPERATION
+----------------------------------------------------------------------------
+checkout --- checks out ZODB object in File-system
+ example:
+ $python sync.py -f /home/user/sandbox
+ -d /zope3/data.fs
+ -s /zope3/site.zcml
+ -o /foo/bar
+ checkout
+ 'or'
+
+ $python sync.py --fspath=/home/user/sandbox
+ --dbpath=/zope3/data.fs
+ --siteconfpath=/zope3/site.zcml
+ --objpath=/foo/bar
+ checkout
+
+ This will download the "bar" folder along with it's contents
+ into the /home/user/sandbox folder. In case if the "bar" module
+ already exist in the sandbox it will be overwritten.
+ Checkout generates the following output:
+ UPDATING foldername
+ U foldername/filename
+
+
+update --- updates the sandbox
+ example:
+ $python sync.py -f /home/user/sandbox/bar
+ -d /zope3/data.fs
+ -s /zope3/site.zcml
+ update
+ 'or'
+
+ $python sync.py --fspath=/home/user/sandbox/bar
+ --dbpath=/zope3/data.fs
+ --siteconfpath=/zope3/site.zcml
+ update
+
+ This will update the contents of "bar" directory in
+ the sandbox.
+
+ An update can undergo various cases like :
+
+ Case1 : When the contents of all the three Sandbox, Original
+ and ZODB for an object is same an update command won't
+ do any changes.
+
+ Case2 : When the contents of the Sandbox and Original are same
+ but ZODB is different, an update command will overwrite
+ Sandbox and Original from ZODB and print the following:
+ U /path/filename.
+
+ Case3 : When the contents of the Original and ZODB are same and
+ the Sandbox is different an update command won't do any
+ changes and print the following:
+ M /path/filename.
+ If the Sandbox contains conflict data the following is
+ printed:
+ C /path/filename.
+
+ Case4 : This is a very unlikely case. When the contents of the
+ Sandbox and ZODB are same but the Original is different
+ an update command will overwrite the Original with the
+ ZODB and print the following:
+ U /path/filename.
+
+ Case5 : When the contents of all the three Sandbox, Original
+ and ZODB are different, an update command will mearge
+ all the changes into the Sandbox and the Original is
+ overwitten by the ZODB and the following is printed:
+ Merging changes in /path/filename
+ In case of a conflict the conflict data is copied into
+ the Sandbox and the Original is overwitten by the ZODB
+ and the following is printed:
+ C Merging changes in /path/filename
+
+ Conventionaly an update has to be done on the sandbox before
+ running commit.
+
+commit --- A commit command copies data from the File-system samdbox
+ into the ZODB
+ example:
+ $python sync.py -f /home/user/sandbox/bar
+ -d /zope3/data.fs
+ -s /zope3/site.zcml
+ commit
+ 'or'
+
+ $python sync.py --fspath=/home/user/sandbox/bar
+ --dbpath=/zope3/data.fs
+ --siteconfpath=/zope3/site.zcml
+ commit
+
+ Commit copies the Sandbox into Original and ZODB, if the ZODB
+ and Original are same or there is no conflict data in the Sandbox
+ and prints the following:
+ /path/filename <-- filename
+ If the ZODB and Original are not same or the Sandbox
+ contains conflict data a commit command won't do anything
+ and will print the following:
+ /path/filename Conflict, Uptodate checkin failed.
+
+
+fcommit --- This is a force commit. A fcommit command will forcefully
+ copy Sandbox
+ into Original and ZODB regardless of any constraints.
+ example:
+ $python sync.py -f /home/user/sandbox/bar
+ -d /zope3/data.fs
+ -s /zope3/site.zcml
+ fcommit
+ 'or'
+
+ $python sync.py --fspath=/home/user/sandbox/bar
+ --dbpath=/zope3/data.fs
+ --siteconfpath=/zope3/site.zcml
+ fcommit
+
+
+diff --- Difference between Three versions of an object
+
+ -1 -- Sandbox and Original
+ -2 -- Sandbox and ZODB
+ -3 -- ZODB and Original
+
+ A diff command will produce the difference of two objects
+ in context output format.
+ example:
+ $python sync.py -2 /home/user/sandbox/bar
+ -d /zope3/data.fs
+ -s /zope3/site.zcml
+ diff
+ 'or'
+
+ $python sync.py -2 /home/user/sandbox/bar
+ --dbpath=/zope3/data.fs
+ --siteconfpath=/zope3/site.zcml
+ diff
+ Default option is -1
+
+
+addtypes --- Displays all the list of types that can be added to the ZODB
+ from the filesystem.
+ example:
+ $python sync.py addtypes
+
+
+add --- Adds objects to file system and saves it to the ZODB on
+ commit.
+ This command will give a list of all the available types
+ that can be added.
+ example:
+ $python sync.py -f /home/user/sandbox/bar
+ -d /zope3/data.fs
+ -s /zope3/site.zcml
+ -t file
+ add file1.html file2.txt file3.xyz
+ 'or'
+
+ $python sync.py --fspath=/home/user/sandbox/bar
+ --dbpath=/zope3/data.fs
+ --siteconfpath=/zope3/site.zcml
+ --type=file
+ add file1.html file2.txt file3.xyz
+
+ This command will add file1.html, file2.txt, file3.xyz in
+ the bar folder of the sandbox and on commit this will be
+ checked in as file type objects in ZODB.
+ If type is not specified with -t option then the types will
+ be checked based on file extensions and only the valid type
+ will be added to the sandbox.
+ File/Folder names with spaces has to be enclosed withing quotes.
+
+
+ENVIRONMENT VARIABLES
+----------------------------------------------------------------------------
+
+SYNCROOT --- Path for the File-system folder where the ZODB object
+ has to be checked out.If not set it takes the default
+ directory. Or can be specified with the --fspath or -f
+ option
+
+ZODBPATH --- Path where the Data.fs file exist in the File-system.
+ if not set it takes the default is ../../Data.fs.
+ Or can be specified with the --dbpath or -d option.
+
+SITECONFPATH --- Path for the site.zcml file.if not set it takes the
+ default is ../../site.zcml. Or can be specified with
+ the --siteconfpath or -s option.
+
+"""