? checkout_modes.patch
Index: jhbuild/config.py
===================================================================
RCS file: /cvs/gnome/jhbuild/jhbuild/config.py,v
retrieving revision 1.25
diff -U5 -r1.25 config.py
--- jhbuild/config.py	19 Jun 2006 14:07:25 -0000	1.25
+++ jhbuild/config.py	10 Jul 2006 16:28:28 -0000
@@ -32,11 +32,12 @@
                 'repos', 'branches',
                 'builddir_pattern', 'module_autogenargs', 'module_makeargs',
                 'interact', 'buildscript', 'nonetwork',
                 'alwaysautogen', 'nobuild', 'makeclean', 'makecheck',
                 'use_lib64', 'tinderbox_outputdir', 'sticky_date',
-                'tarballdir', 'pretty_print' ]
+                'tarballdir', 'pretty_print', 'checkout_mode', 'copy_dir' ,
+                'module_checkout_mode']
 
 env_prepends = {}
 def prependpath(envvar, path):
     env_prepends.setdefault(envvar, []).append(path)
 
Index: jhbuild/defaults.jhbuildrc
===================================================================
RCS file: /cvs/gnome/jhbuild/jhbuild/defaults.jhbuildrc,v
retrieving revision 1.19
diff -U5 -r1.19 defaults.jhbuildrc
--- jhbuild/defaults.jhbuildrc	17 May 2006 12:03:26 -0000	1.19
+++ jhbuild/defaults.jhbuildrc	10 Jul 2006 16:28:28 -0000
@@ -44,10 +44,19 @@
 makeclean     = False  # run make clean before building
 makecheck     = False  # run make check after building
 
 interact      = True   # whether to interact with the user.
 
+# checkout modes. For VCS directories, it specifies how the checkout
+# is done. We can also specify checkout modes for specific modules
+checkout_mode = 'update'
+module_checkout_mode = {}
+
+# in case we use the copy checkout mode, we can set up a copy dir. Defaults to
+# checkout dir
+copy_dir = None
+
 # whether to install to lib64 directories?  Currently this will default to
 # True on Linux AMD64, PPC64 or S390x systems, and False everywhere else.
 # Patches accepted to fix the default for other architectures.
 uname = os.uname()
 use_lib64 = (uname[0], uname[4]) in [ ('Linux', 'x86_64'),
Index: jhbuild/modtypes/tarball.py
===================================================================
RCS file: /cvs/gnome/jhbuild/jhbuild/modtypes/tarball.py,v
retrieving revision 1.39
diff -U5 -r1.39 tarball.py
--- jhbuild/modtypes/tarball.py	18 May 2006 10:34:14 -0000	1.39
+++ jhbuild/modtypes/tarball.py	10 Jul 2006 16:28:29 -0000
@@ -111,10 +111,14 @@
                        (self.source_md5, sum.hexdigest())
 
     def do_start(self, buildscript):
         # check if jhbuild previously built it ...
         checkoutdir = self.get_builddir(buildscript)
+        if (buildscript.config.checkout_mode == 'clobber'):
+            buildscript.execute('rm -rf '+self.get_srcdir(buildscript))
+            buildscript.packagedb.add(self.name, '')
+
         if buildscript.packagedb.check(self.name, self.version):
             return (self.STATE_DONE, None, None)
 
         return (self.STATE_DOWNLOAD, None, None)
 
Index: jhbuild/versioncontrol/__init__.py
===================================================================
RCS file: /cvs/gnome/jhbuild/jhbuild/versioncontrol/__init__.py,v
retrieving revision 1.3
diff -U5 -r1.3 __init__.py
--- jhbuild/versioncontrol/__init__.py	14 Jun 2006 02:35:56 -0000	1.3
+++ jhbuild/versioncontrol/__init__.py	10 Jul 2006 16:28:29 -0000
@@ -51,10 +51,12 @@
     def branch_from_xml(self, name, branchnode):
         kws = {}
         for attr in self.branch_xml_attrs:
             if branchnode.hasAttribute(attr):
                 kws[attr.replace('-', '_')] = branchnode.getAttribute(attr)
+        if branchnode.hasAttribute('id'):
+            kws['branch_id'] = branchnode.getAttribute('id')
         return self.branch(name, **kws)
 
 
 class Branch:
     """An abstract class representing a branch in a repository."""
Index: jhbuild/versioncontrol/cvs.py
===================================================================
RCS file: /cvs/gnome/jhbuild/jhbuild/versioncontrol/cvs.py,v
retrieving revision 1.6
diff -U5 -r1.6 cvs.py
--- jhbuild/versioncontrol/cvs.py	14 Jun 2006 02:35:56 -0000	1.6
+++ jhbuild/versioncontrol/cvs.py	10 Jul 2006 16:28:29 -0000
@@ -25,10 +25,11 @@
 __metaclass__ = type
 
 import sys
 import os
 import md5
+import distutils
 
 
 from jhbuild.errors import BuildStateError
 from jhbuild.versioncontrol import Repository, Branch, register_repo_type
 
@@ -216,11 +217,40 @@
 
     def branchname(self):
         return self.revision
     branchname = property(branchname)
 
-    def _checkout(self, buildscript):
+    def _checkout_mode(self):
+        checkout_mode = self.config.checkout_mode
+        if self.config.module_checkout_mode.get(self.module) is not None:
+            checkout_mode = self.config.module_checkout_mode[self.module]
+        return checkout_mode
+    checkout_mode = property(_checkout_mode)
+
+    def _wipedir(self, buildscript):
+        if (os.path.exists(self.srcdir)):
+            for root, dirs, files in os.walk(self.srcdir, topdown=False):
+                for name in files:
+                    os.remove(os.path.join(root, name))
+                for name in dirs:
+                    os.rmdir(os.path.join(root, name))
+
+    def _export(self, buildscript):
+        cmd = ['cvs', '-z3', '-q', '-d', self.repository.cvsroot,
+               'export']
+        if self.revision:
+            cmd.extend(['-r', self.revision])
+        else:
+            cmd.extend(['-r', 'HEAD'])
+        if self.config.sticky_date:
+            cmd.extend(['-D', self.config.sticky_date])
+        if self.checkoutdir and self.override_checkoutdir:
+            cmd.extend(['-d', self.checkoutdir])
+        cmd.append(self.module)
+        buildscript.execute(cmd, 'cvs', cwd=self.config.checkoutroot)
+
+    def _checkout(self, buildscript, copydir=None):
         cmd = ['cvs', '-z3', '-q', '-d', self.repository.cvsroot,
                'checkout', '-P']
         if self.revision:
             cmd.extend(['-r', self.revision])
         if self.config.sticky_date:
@@ -228,19 +258,26 @@
         if not (self.revision or self.config.sticky_date):
             cmd.append('-A')
         if self.checkoutdir and self.override_checkoutdir:
             cmd.extend(['-d', self.checkoutdir])
         cmd.append(self.module)
-        buildscript.execute(cmd, 'cvs', cwd=self.config.checkoutroot)
+        if (copydir is not None):
+            buildscript.execute(cmd, 'cvs', cwd=copydir)
+        else:
+            buildscript.execute(cmd, 'cvs', cwd=self.config.checkoutroot)
 
-    def _update(self, buildscript):
+    def _update(self, buildscript, copydir=None):
         # sanity check the existing working tree:
+        if (copydir is not None):
+            outputdir = os.path.join(copydir, self.module)
+        else:
+            outputdir = self.srcdir
         try:
-            wc_root = check_root(self.srcdir)
+            wc_root = check_root(outputdir)
         except IOError:
             raise BuildStateError('"%s" does not appear to be a CVS working '
-                                  'copy' % os.path.abspath(self.srcdir))
+                                  'copy' % os.path.abspath(outputdir))
         if wc_root != self.repository.cvsroot:
             raise BuildStateError('working copy points at the wrong '
                                   'repository (expected %s but got %s). '
                                   'Consider using the changecvsroot.py '
                                   'script to fix this.'
@@ -256,17 +293,43 @@
         if self.config.sticky_date:
             cmd.extend(['-D', self.config.sticky_date])
         if not (self.revision or self.config.sticky_date):
             cmd.append('-A')
         cmd.append('.')
-        buildscript.execute(cmd, 'cvs', cwd=self.srcdir)
+        buildscript.execute(cmd, 'cvs', cwd=outputdir)
+
+    def _copy(self, copydir):
+
+        module = self.module
+        if self.checkoutdir and self.override_checkoutdir:
+            module =self.checkoutdir
+        fromdir = os.path.join(copydir, module)
+        todir = os.path.join(self.config.checkoutroot, module)
+        distutils.dir_util.copy_tree(fromdir, todir)
 
     def checkout(self, buildscript):
-        if os.path.exists(self.srcdir):
-            self._update(buildscript)
-        else:
-            self._checkout(buildscript)
+        if self.checkout_mode in ('clobber', 'export'):
+            self._wipedir(buildscript)
+            if (self.checkout_mode == 'clobber'):
+                self._checkout(buildscript)
+            else:
+                self._export(buildscript)
+        elif self.checkout_mode in ('update', 'copy'):
+            copydir = None
+            if (self.checkout_mode == 'copy' and
+                self.config.copy_dir is not None):
+                copydir = self.config.copy_dir
+            else:
+                copydir = self.config.checkoutroot
+            if os.path.exists(os.path.join(copydir, self.module, 'CVS')):
+                self._update(buildscript, copydir)
+            else:
+                self._wipedir(buildscript)
+                self._checkout(buildscript, copydir)
+            if (self.checkout_mode == 'copy' and
+                self.config.copy_dir is not None):
+                self._copy(copydir)
 
     def force_checkout(self, buildscript):
         self._checkout(buildscript)
 
     def tree_id(self):
Index: jhbuild/versioncontrol/git.py
===================================================================
RCS file: /cvs/gnome/jhbuild/jhbuild/versioncontrol/git.py,v
retrieving revision 1.7
diff -U5 -r1.7 git.py
--- jhbuild/versioncontrol/git.py	14 Jun 2006 02:35:56 -0000	1.7
+++ jhbuild/versioncontrol/git.py	10 Jul 2006 16:28:29 -0000
@@ -20,10 +20,11 @@
 __all__ = []
 __metaclass__ = type
 
 import os
 import urlparse
+import distutils
 
 from jhbuild.errors import FatalError
 from jhbuild.utils.cmds import get_output
 from jhbuild.versioncontrol import Repository, Branch, register_repo_type
 
@@ -84,30 +85,90 @@
 
     def branchname(self):
         return None
     branchname = property(branchname)
 
-    def _checkout(self, buildscript):
+    def _checkout_mode(self):
+        checkout_mode = self.config.checkout_mode
+        if self.config.module_checkout_mode.get(os.path.basename(self.module)) is not None:
+            checkout_mode = self.config.module_checkout_mode[os.path.basename(self.module)]
+        return checkout_mode
+    checkout_mode = property(_checkout_mode)
+
+    def _wipedir(self, buildscript):
+        if (os.path.exists(self.srcdir)):
+            for root, dirs, files in os.walk(self.srcdir, topdown=False):
+                for name in files:
+                    os.remove(os.path.join(root, name))
+                for name in dirs:
+                    os.rmdir(os.path.join(root, name))
+            os.rmdir(self.srcdir)
+
+    def _export(self, buildscript):
+        cmd = ['svn', 'export', self.module]
+
+        if self.checkoutdir:
+            cmd.append(self.checkoutdir)
+
+        if self.config.sticky_date:
+            cmd.extend(['-r', '{%s}' % self.config.sticky_date])
+
+        buildscript.execute(cmd, 'svn', cwd=self.config.checkoutroot)
+    
+    def _checkout(self, buildscript, copydir = None):
         cmd = ['git', 'clone', self.module]
         if self.checkoutdir:
             cmd.append(self.checkoutdir)
 
         if self.config.sticky_date:
             raise FatalError('date based checkout not yet supported\n')
 
-        buildscript.execute(cmd, 'git', cwd=self.config.checkoutroot)
+        if (copydir is not None):
+            buildscript.execute(cmd, 'git', cwd=copydir)
+        else:
+            buildscript.execute(cmd, 'git', cwd=self.config.checkoutroot)
 
-    def _update(self, buildscript):
+    def _update(self, buildscript, copydir=None):
+        if (copydir is not None):
+            outputdir = os.path.join(copydir, os.path.basename(self.module))
+        else:
+            outputdir = self.srcdir
         if self.config.sticky_date:
             raise FatalError('date based checkout not yet supported\n')
-        buildscript.execute(['git', 'pull'], 'git', cwd=self.srcdir)
+        buildscript.execute(['git', 'pull'], 'git', cwd=outputdir)
+
+    def _copy(self, copydir):
+        module = self.module
+        if self.checkoutdir and self.override_checkoutdir:
+            module =self.checkoutdir
+        fromdir = os.path.join(copydir, os.path.basename(module))
+        todir = os.path.join(self.config.checkoutroot, os.path.basename(module))
+        distutils.dir_util.copy_tree(fromdir, todir)
 
     def checkout(self, buildscript):
-        if os.path.exists(self.srcdir):
-            self._update(buildscript)
-        else:
-            self._checkout(buildscript)
+        if self.checkout_mode in ('clobber', 'export'):
+            self._wipedir(buildscript)
+            if (self.checkout_mode == 'clobber'):
+                self._checkout(buildscript)
+            else:
+                self._checkout(buildscript)
+        elif self.checkout_mode in ('update', 'copy'):
+            copydir = None
+            if (self.checkout_mode == 'copy' and
+                self.config.copy_dir is not None):
+                copydir = self.config.copy_dir
+            else:
+                copydir = self.config.checkoutroot
+                
+            if os.path.exists(os.path.join(copydir, os.path.basename(self.module),'.git')):
+                self._update(buildscript, copydir)
+            else:
+                self._wipedir(buildscript)
+                self._checkout(buildscript, copydir)
+            if (self.checkout_mode == 'copy' and
+                self.config.copy_dir is not None):
+                self._copy(copydir)
 
     def tree_id(self):
         if not os.path.exists(self.srcdir):
             return None
         output = get_output(['git-rev-parse', 'master'],
Index: jhbuild/versioncontrol/svn.py
===================================================================
RCS file: /cvs/gnome/jhbuild/jhbuild/versioncontrol/svn.py,v
retrieving revision 1.6
diff -U5 -r1.6 svn.py
--- jhbuild/versioncontrol/svn.py	14 Jun 2006 02:35:56 -0000	1.6
+++ jhbuild/versioncontrol/svn.py	10 Jul 2006 16:28:29 -0000
@@ -20,10 +20,11 @@
 __all__ = []
 __metaclass__ = type
 
 import os
 import urlparse
+import distutils.dir_util
 
 from jhbuild.errors import CommandError, BuildStateError, FatalError
 from jhbuild.utils.cmds import get_output
 from jhbuild.versioncontrol import Repository, Branch, register_repo_type
 
@@ -123,39 +124,101 @@
             elif part == 'trunk':
                 break
         return None
     branchname = property(branchname)
 
-    def _checkout(self, buildscript):
-        cmd = ['svn', 'checkout', self.module]
+    def _checkout_mode(self):
+        checkout_mode = self.config.checkout_mode
+        if self.config.module_checkout_mode.get(os.path.basename(self.module)) is not None:
+            checkout_mode = self.config.module_checkout_mode[os.path.basename(self.module)]
+        return checkout_mode
+    checkout_mode = property(_checkout_mode)
+
+    def _wipedir(self, buildscript):
+        if (os.path.exists(self.srcdir)):
+            for root, dirs, files in os.walk(self.srcdir, topdown=False):
+                for name in files:
+                    os.remove(os.path.join(root, name))
+                for name in dirs:
+                    os.rmdir(os.path.join(root, name))
+            os.rmdir(self.srcdir)
+
+    def _export(self, buildscript):
+        cmd = ['svn', 'export', self.module]
 
         if self.checkoutdir:
             cmd.append(self.checkoutdir)
 
         if self.config.sticky_date:
             cmd.extend(['-r', '{%s}' % self.config.sticky_date])
 
         buildscript.execute(cmd, 'svn', cwd=self.config.checkoutroot)
     
-    def _update(self, buildscript):
+    def _checkout(self, buildscript, copydir=None):
+        cmd = ['svn', 'checkout', self.module]
+
+        if self.checkoutdir:
+            cmd.append(self.checkoutdir)
+
+        if self.config.sticky_date:
+            cmd.extend(['-r', '{%s}' % self.config.sticky_date])
+
+        if (copydir is not None):
+            buildscript.execute(cmd, 'svn', cwd=copydir)
+        else:
+            buildscript.execute(cmd, 'svn', cwd=self.config.checkoutroot)
+    
+    def _update(self, buildscript, copydir=None):
         opt = []
+        if (copydir is not None):
+            outputdir = os.path.join(copydir, os.path.basename(self.module))
+        else:
+            outputdir = self.srcdir
+
         if self.config.sticky_date:
             opt.extend(['-r', '{%s}' % self.config.sticky_date])
 
         # if the URI doesn't match, use "svn switch" instead of "svn update"
-        if get_uri(self.srcdir) != self.module:
+        if get_uri(outputdir) != self.module:
             cmd = ['svn', 'switch'] + opt + [self.module]
         else:
             cmd = ['svn', 'update'] + opt + ['.']
 
-        buildscript.execute(cmd, 'svn', cwd=self.srcdir)
+        buildscript.execute(cmd, 'svn', cwd=outputdir)
+
+    def _copy(self, copydir):
+
+        module = self.module
+        if self.checkoutdir and self.override_checkoutdir:
+            module =self.checkoutdir
+        fromdir = os.path.join(copydir, os.path.basename(module))
+        todir = os.path.join(self.config.checkoutroot, os.path.basename(module))
+        distutils.dir_util.copy_tree(fromdir, todir)
 
     def checkout(self, buildscript):
-        if os.path.exists(self.srcdir):
-            self._update(buildscript)
-        else:
-            self._checkout(buildscript)
+        if self.checkout_mode in ('clobber', 'export'):
+            self._wipedir(buildscript)
+            if (self.checkout_mode == 'clobber'):
+                self._checkout(buildscript)
+            else:
+                self._export(buildscript)
+        elif self.checkout_mode in ('update', 'copy'):
+            copydir = None
+            if (self.checkout_mode == 'copy' and
+                self.config.copy_dir is not None):
+                copydir = self.config.copy_dir
+            else:
+                copydir = self.config.checkoutroot
+                
+            if os.path.exists(os.path.join(copydir, os.path.basename(self.module),'.svn')):
+                self._update(buildscript, copydir)
+            else:
+                self._wipedir(buildscript)
+                self._checkout(buildscript, copydir)
+            if (self.checkout_mode == 'copy' and
+                self.config.copy_dir is not None):
+                self._copy(copydir)
 
     def force_checkout(self, buildscript):
         self._checkout(buildscript)
 
     def tree_id(self):
Index: jhbuild/versioncontrol/tarball.py
===================================================================
RCS file: /cvs/gnome/jhbuild/jhbuild/versioncontrol/tarball.py,v
retrieving revision 1.4
diff -U5 -r1.4 tarball.py
--- jhbuild/versioncontrol/tarball.py	14 Jun 2006 10:02:40 -0000	1.4
+++ jhbuild/versioncontrol/tarball.py	10 Jul 2006 16:28:29 -0000
@@ -57,11 +57,11 @@
             if module is None:
                 module = name
             module = urlparse.urljoin(self.href, module)
         return TarballBranch(self, module=module, version=version,
                              checkoutdir=checkoutdir,
-                             source_size=int(size), source_md5=md5sum)
+                             source_size=int(size), source_md5=md5sum, branch_id=name)
 
     def branch_from_xml(self, name, branchnode):
         branch = Repository.branch_from_xml(self, name, branchnode)
         # patches represented as children of the branch node
         for childnode in branchnode.childNodes:
@@ -78,19 +78,20 @@
 
 class TarballBranch(Branch):
     """A class representing a Tarball."""
 
     def __init__(self, repository, module, version, checkoutdir,
-                 source_size, source_md5):
+                 source_size, source_md5, branch_id):
         self.repository = repository
         self.config = repository.config
         self.module = module
         self.version = version
         self.checkoutdir = checkoutdir
         self.source_size = source_size
         self.source_md5 = source_md5
         self.patches = []
+        self.branch_id = branch_id
 
     def _local_tarball(self):
         basename = os.path.basename(self.module)
         if not basename:
             raise FatalError('URL has no filename component: %s' % self.module)
@@ -174,11 +175,29 @@
             buildscript.execute('patch -p%d < "%s"'
                                 % (patchstrip, patchfile),
                                 cwd=self.srcdir)
                 
 
+    def _checkout_mode(self):
+        checkout_mode = self.config.checkout_mode
+        if self.config.module_checkout_mode.get(self.branch_id) is not None:
+            checkout_mode = self.config.module_checkout_mode[self.branch_id]
+        return checkout_mode
+    checkout_mode = property(_checkout_mode)
+
+    def _wipedir(self, buildscript):
+        if (os.path.exists(self.srcdir)):
+            for root, dirs, files in os.walk(self.srcdir, topdown=False):
+                for name in files:
+                    os.remove(os.path.join(root, name))
+                for name in dirs:
+                    os.rmdir(os.path.join(root, name))
+            os.rmdir(self.srcdir)
+
     def checkout(self, buildscript):
+        if self.checkout_mode == 'clobber':
+            self._wipedir(buildscript)
         if not os.path.exists(self.srcdir):
             self._download_and_unpack(buildscript)
 
     def force_checkout(self, buildscript):
         self._download_and_unpack(buildscript)
