[gnome-ostree/wip/integrated-build: 2/2] Move all sources into git submodules



commit cf456c10e1ee39e1175d41ee7dcaba5302932eaf
Author: Colin Walters <walters verbum org>
Date:   Fri Sep 21 17:05:08 2012 -0400

    Move all sources into git submodules
    
    Git submodules were designed to do exactly what we're doing.  While
    they have some major drawbacks, I think the benefits outweigh the
    drawbacks.
    
    For example, we can speak of "git revision a19e3 of gnome-ostree"
    which in turn points to exact revisions of every component. This makes
    it far easier to do coordinated changes; you can send a patch that
    touches three components, plus the manifest.

 Makefile-ostbuild.am                               |    9 +-
 deleted-components/README                          |    2 +
 gnomeos-3.6.json => manifest.json                  |    2 +-
 src/ostbuild/pyostbuild/builtin_build.py           |   83 +++---------
 src/ostbuild/pyostbuild/builtin_checkout.py        |  120 ------------------
 src/ostbuild/pyostbuild/builtin_git_mirror.py      |  105 ---------------
 src/ostbuild/pyostbuild/builtin_import_tree.py     |   96 --------------
 src/ostbuild/pyostbuild/builtin_prefix.py          |   73 -----------
 src/ostbuild/pyostbuild/builtin_resolve.py         |  134 --------------------
 src/ostbuild/pyostbuild/builtin_submodule_fetch.py |   86 +++++++++++++
 src/ostbuild/pyostbuild/builtin_submodule_sync.py  |  119 +++++++++++++++++
 src/ostbuild/pyostbuild/builtins.py                |   78 ++++--------
 src/ostbuild/pyostbuild/git.py                     |   61 +++++++++
 src/ostbuild/pyostbuild/jsondb.py                  |  112 ----------------
 src/ostbuild/pyostbuild/main.py                    |    7 +-
 15 files changed, 320 insertions(+), 767 deletions(-)
---
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..e69de29
diff --git a/Makefile-ostbuild.am b/Makefile-ostbuild.am
index b8035c4..c7ace39 100644
--- a/Makefile-ostbuild.am
+++ b/Makefile-ostbuild.am
@@ -36,24 +36,21 @@ pyostbuilddir=$(libdir)/ostbuild/pyostbuild
 pyostbuild_PYTHON =					\
 	src/ostbuild/pyostbuild/buildutil.py		\
 	src/ostbuild/pyostbuild/builtin_build.py	\
-	src/ostbuild/pyostbuild/builtin_checkout.py	\
 	src/ostbuild/pyostbuild/builtin_deploy_qemu.py	\
 	src/ostbuild/pyostbuild/builtin_deploy_root.py	\
 	src/ostbuild/pyostbuild/builtin_run_qemu.py	\
-	src/ostbuild/pyostbuild/builtin_import_tree.py	\
 	src/ostbuild/pyostbuild/builtin_privhelper_deploy_qemu.py	\
 	src/ostbuild/pyostbuild/builtin_privhelper_run_qemu.py	\
-	src/ostbuild/pyostbuild/builtin_git_mirror.py	\
-	src/ostbuild/pyostbuild/builtin_prefix.py	\
 	src/ostbuild/pyostbuild/builtin_repoweb_json.py	\
-	src/ostbuild/pyostbuild/builtin_resolve.py	\
 	src/ostbuild/pyostbuild/builtin_init.py	\
 	src/ostbuild/pyostbuild/builtin_source_diff.py	\
+	src/ostbuild/pyostbuild/builtin_submodule_sync.py	\
+	src/ostbuild/pyostbuild/builtin_submodule_fetch.py	\
 	src/ostbuild/pyostbuild/builtins.py		\
 	src/ostbuild/pyostbuild/filemonitor.py		\
 	src/ostbuild/pyostbuild/fileutil.py		\
+	src/ostbuild/pyostbuild/git.py			\
 	src/ostbuild/pyostbuild/__init__.py		\
-	src/ostbuild/pyostbuild/jsondb.py		\
 	src/ostbuild/pyostbuild/kvfile.py		\
 	src/ostbuild/pyostbuild/main.py			\
 	src/ostbuild/pyostbuild/mainloop.py		\
diff --git a/deleted-components/README b/deleted-components/README
new file mode 100644
index 0000000..0efb3f5
--- /dev/null
+++ b/deleted-components/README
@@ -0,0 +1,2 @@
+Components that used to exist but are no longer listed in the manifest
+are moved here for safety.
diff --git a/gnomeos-3.6.json b/manifest.json
similarity index 99%
rename from gnomeos-3.6.json
rename to manifest.json
index 8568649..db01abb 100644
--- a/gnomeos-3.6.json
+++ b/manifest.json
@@ -1,5 +1,5 @@
 {
-  "00ostbuild-manifest-version": 0,
+  "00ostbuild-manifest-version": 1,
 
   "prefix": "gnomeos-3.6",
   "architectures": ["i686"],
diff --git a/src/ostbuild/pyostbuild/builtin_build.py b/src/ostbuild/pyostbuild/builtin_build.py
index 7737f00..a33c319 100755
--- a/src/ostbuild/pyostbuild/builtin_build.py
+++ b/src/ostbuild/pyostbuild/builtin_build.py
@@ -178,8 +178,13 @@ class OstbuildBuild(builtins.Builtin):
     def _needs_rebuild(self, previous_metadata, new_metadata):
         build_keys = ['config-opts', 'src', 'revision']
         for k in build_keys:
-            if (k not in new_metadata) or (previous_metadata[k] != new_metadata[k]):
-                return 'key %r differs' % (k, )
+            if (k not in new_metadata):
+                return 'key %r removed from new_metadata' % (k, )
+            if k in previous_metadata:
+                oldval = previous_metadata[k]
+                newval = new_metadata[k]
+                if oldval != newval:
+                    return 'key %r differs (%r -> %r)' % (k, oldval, newval)
             
         if 'patches' in previous_metadata:
             if 'patches' not in new_metadata:
@@ -198,8 +203,8 @@ class OstbuildBuild(builtins.Builtin):
                 return 'patch sha256sums differ'
         return None
 
-    def _compute_sha256sums_for_patches(self, patchdir, component):
-        patches = buildutil.get_patch_paths_for_component(patchdir, component)
+    def _compute_sha256sums_for_patches(self, component):
+        patches = buildutil.get_patch_paths_for_component(self.srcdir, component)
         result = []
 
         for patch in patches:
@@ -217,9 +222,10 @@ class OstbuildBuild(builtins.Builtin):
         buildname = '%s/%s/%s' % (self.snapshot['prefix'], basename, architecture)
         build_ref = 'components/%s' % (buildname, )
 
-        current_vcs_version = component.get('revision')
+        expanded_component = component
+        expanded_component['revision'] = buildutil.get_git_version_describe(self._component_abspath(component))
 
-        expanded_component = self.expand_component(component)
+        current_vcs_version = expanded_component.get('revision')
 
         skip_rebuild = self.args.compose_only
 
@@ -244,27 +250,8 @@ class OstbuildBuild(builtins.Builtin):
                 fatal("--compose-only specified but no previous build of %s found" % (buildname, ))
 
         if 'patches' in expanded_component:
-            patches_revision = expanded_component['patches']['revision']
-            if self.args.patches_path:
-                patchdir = self.args.patches_path
-            elif self.cached_patchdir_revision == patches_revision:
-                patchdir = self.patchdir
-            else:
-                patchdir = vcs.checkout_patches(self.mirrordir,
-                                                self.patchdir,
-                                                expanded_component,
-                                                patches_path=self.args.patches_path)
-                self.cached_patchdir_revision = patches_revision
-            if ((previous_metadata is not None) and
-                'patches' in previous_metadata and
-                previous_metadata['patches']['revision'] == patches_revision):
-                # Copy over the sha256sums
-                expanded_component['patches'] = previous_metadata['patches']
-            else:
-                patches_sha256sums = self._compute_sha256sums_for_patches(patchdir, expanded_component)
-                expanded_component['patches']['files_sha256sums'] = patches_sha256sums
-        else:
-            patchdir = None
+            patches_sha256sums = self._compute_sha256sums_for_patches(expanded_component)
+            expanded_component['patches']['files_sha256sums'] = patches_sha256sums
 
         force_rebuild = (self.buildopts.force_rebuild or
                          basename in self.force_build_components)
@@ -286,22 +273,9 @@ class OstbuildBuild(builtins.Builtin):
         json.dump(expanded_component, f, indent=4, sort_keys=True)
         f.close()
 
-        checkoutdir = os.path.join(self.workdir, 'checkouts')
-        component_src = os.path.join(checkoutdir, buildname)
-        fileutil.ensure_parent_dir(component_src)
-        child_args = ['ostbuild', 'checkout', '--snapshot=' + self.snapshot_path,
-                      '--checkoutdir=' + component_src,
-                      '--metadata-path=' + temp_metadata_path]
+        component_src = self._component_abspath(expanded_component)
         if not self.buildopts.no_clean:
-            child_args.append('--clean')
-        child_args.extend(['--overwrite', basename])
-        if self.args.patches_path:
-            child_args.append('--patches-path=' + self.args.patches_path)
-        elif patchdir is not None:
-            child_args.append('--patches-path=' + patchdir)
-        run_sync(child_args)
-
-        os.unlink(temp_metadata_path)
+            run_sync(['git', 'clean', '-d', '-f', '-x'], cwd=component_src)
 
         logdir = os.path.join(self.workdir, 'logs', buildname)
         fileutil.ensure_dir(logdir)
@@ -353,6 +327,8 @@ class OstbuildBuild(builtins.Builtin):
                            '--ostbuild-meta=_ostbuild-meta.json'])
         env_copy = dict(buildutil.BUILD_ENV)
         env_copy['PWD'] = chroot_sourcedir
+        # Used to unbreak pulseaudio's git-version-gen
+        env_copy['GIT_DESCRIBE_FOR_BUILD'] = expanded_component['revision']
 
         log("Logging to %s" % (log_path, ))
         f = open(log_path, 'w')
@@ -392,10 +368,6 @@ class OstbuildBuild(builtins.Builtin):
             os.unlink(statoverride_path)
 
         if not self.args.no_clean_results:
-            if os.path.islink(component_src):
-                os.unlink(component_src)
-            else:
-                shutil.rmtree(component_src)
             shutil.rmtree(component_resultdir)
 
         return run_sync_get_output(['ostree', '--repo=' + self.repo,
@@ -500,23 +472,16 @@ and the manifest input."""
     def _build_base(self):
         """Build the Yocto base system."""
         basemeta = self.snapshot['base']
-        checkoutdir = os.path.join(self.workdir, 'checkouts', basemeta['name'])
-        fileutil.ensure_parent_dir(checkoutdir)
-
-        (keytype, uri) = buildutil.parse_src_key(basemeta['src'])
-        vcs.get_vcs_checkout(self.mirrordir, keytype, uri, checkoutdir,
-                             basemeta['revision'],
-                             overwrite=False)
-
         builddir = os.path.join(self.workdir, 'build-' + basemeta['name'])
         image_deploy_dir = os.path.join(builddir, 'tmp-eglibc', 'deploy', 'images')
         repo_link = os.path.join(image_deploy_dir, 'repo')
         if not os.path.islink(repo_link):
             os.symlink(self.repo, repo_link)
 
+        src = self._component_abspath(basemeta)
         cmd = ['linux-user-chroot', '--unshare-pid', '/',
                os.path.join(LIBDIR, 'ostbuild', 'ostree-build-yocto'),
-               checkoutdir, builddir]
+               src, builddir]
         # We specifically want to kill off any environment variables jhbuild
         # may have set.
         run_sync(cmd, env=buildutil.BUILD_ENV)
@@ -524,8 +489,6 @@ and the manifest input."""
     def execute(self, argv):
         parser = argparse.ArgumentParser(description=self.short_description)
         parser.add_argument('--prefix')
-        parser.add_argument('--src-snapshot')
-        parser.add_argument('--patches-path')
         parser.add_argument('--status-json-path',
                             help="Write data to this JSON file as build progresses")
         parser.add_argument('--force-rebuild', action='store_true')
@@ -541,9 +504,7 @@ and the manifest input."""
         self.args = args
         
         self.parse_config()
-        self.parse_snapshot(args.prefix, args.src_snapshot)
-
-        log("Using source snapshot: %s" % (os.path.basename(self.snapshot_path), ))
+        self.parse_snapshot()
 
         self._write_status({'state': 'build-starting'})
 
@@ -555,8 +516,6 @@ and the manifest input."""
 
         self.force_build_components = set()
 
-        self.cached_patchdir_revision = None
-
         self._initialize_repo()
         self._build_base()
 
diff --git a/src/ostbuild/pyostbuild/builtin_submodule_fetch.py b/src/ostbuild/pyostbuild/builtin_submodule_fetch.py
new file mode 100755
index 0000000..dd3eb70
--- /dev/null
+++ b/src/ostbuild/pyostbuild/builtin_submodule_fetch.py
@@ -0,0 +1,86 @@
+# Copyright (C) 2011,2012 Colin Walters <walters verbum org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+import os,sys,subprocess,tempfile,re,shutil
+import copy
+import argparse
+import json
+import time
+import urlparse
+from StringIO import StringIO
+
+from . import builtins
+from .ostbuildlog import log, fatal
+from .subprocess_helpers import run_sync, run_sync_get_output
+from . import ostbuildrc
+from . import vcs
+from . import git
+from . import buildutil
+from . import kvfile
+from . import odict
+
+class OstbuildSubmoduleFetch(builtins.Builtin):
+    name = "submodule-fetch"
+    short_description = "Fetch from tracked submodules" 
+
+    def __init__(self):
+        builtins.Builtin.__init__(self)
+
+    def _fetch_rebase_update_recurse(self, checkout, branch=None):
+        if branch is not None:
+            rebase_target = 'origin/' + branch
+        else:
+            rebase_target = checkout.get_head()
+        checkout.fetch()
+        checkout.rebase(rebase_target)
+        checkout.submodule_update()
+        for csum, modpath, rest in checkout.enumerate_submodules():
+            fullpath = os.path.join(checkout.path, modpath)
+            subcheckout = git.GitCheckout(fullpath)
+            self._fetch_rebase_update_recurse(subcheckout)
+
+    def _fetch_submodule(self, component):
+        tag = component.get('tag')
+        if tag is not None:
+            return
+
+        component_path = self._component_path(component)
+        branch = component.get('branch') or 'master'
+        
+        checkout = git.GitCheckout(component_path)
+        self._fetch_rebase_update_recurse(checkout, branch=branch)
+
+    def execute(self, argv):
+        parser = argparse.ArgumentParser(description=self.short_description)
+        parser.add_argument('components', nargs='*')
+
+        args = parser.parse_args(argv)
+
+        self.parse_config()
+        self.parse_snapshot()
+
+        if len(args.components) > 0:
+            components = args.components
+        else:
+            components = map(lambda x: x['name'], self.snapshot['components'])
+
+        self._fetch_submodule(self.snapshot['base'])
+        for component_name in components:
+            component = self.get_component(component_name)
+            self._fetch_submodule(component)
+        
+builtins.register(OstbuildSubmoduleFetch)
diff --git a/src/ostbuild/pyostbuild/builtin_submodule_sync.py b/src/ostbuild/pyostbuild/builtin_submodule_sync.py
new file mode 100755
index 0000000..5ab2f1d
--- /dev/null
+++ b/src/ostbuild/pyostbuild/builtin_submodule_sync.py
@@ -0,0 +1,119 @@
+# Copyright (C) 2011,2012 Colin Walters <walters verbum org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+import os,sys,subprocess,tempfile,re,shutil
+import copy
+import argparse
+import json
+import time
+import urlparse
+from StringIO import StringIO
+
+from . import builtins
+from .ostbuildlog import log, fatal
+from .subprocess_helpers import run_sync, run_sync_get_output
+from . import ostbuildrc
+from . import vcs
+from . import git
+from . import buildutil
+from . import kvfile
+from . import odict
+
+class OstbuildSubmoduleSync(builtins.Builtin):
+    name = "submodule-sync"
+    short_description = "Reset submodules to content from manifest" 
+
+    def __init__(self):
+        builtins.Builtin.__init__(self)
+
+    def _recursive_git_config(self, cwd, key, value):
+        run_sync(['git', 'config', key, value], cwd=cwd)
+        checkout = git.GitCheckout(cwd)
+        for csum, modpath, rest in checkout.enumerate_submodules():
+            subpath=os.path.join(cwd, modpath)
+            self._recursive_git_config(subpath, key, value)
+
+    def _ensure_submodule(self, component):
+        component_path = self._component_path(component)
+        branch = component.get('branch')
+        tag = component.get('tag')
+        (keytype, uri) = vcs.parse_src_key(component['src'])
+        if not os.path.isdir(component_path):
+            run_sync(['git', 'submodule', 'add', uri, component_path])
+
+    def _sync_submodule(self, component):
+        component_path = self._component_path(component)
+        branch = component.get('branch')
+        if branch:
+            branch = 'origin/' + branch
+        tag = component.get('tag')
+        tag_or_branch = tag or branch
+        log("Syncing %s to %s" % (component['name'], tag_or_branch))
+        run_sync(['git', 'clean', '-d', '-f', '-x'], cwd=component_path, log_initiation=False)
+        run_sync(['git', 'checkout', '-f', '-q', tag_or_branch], cwd=component_path,
+                 log_initiation=False)
+        run_sync(['git', 'submodule', 'init'], cwd=component_path,
+                 log_initiation=False)
+        run_sync(['git', 'submodule', 'update', '--recursive'], cwd=component_path,
+                 log_initiation=False)
+        # This ensures that we won't GC commit objects, thus we'll always have
+        # the source code for binaries we've potentially built code from.
+        self._recursive_git_config(component_path, 'gc.auto', '0')
+        if 'patches' in component:
+            for patch in component['patches']['files']:
+                patch_path = os.path.join(self.srcdir, 'patches', patch)
+                run_sync(['git', 'am', '--ignore-date', '-3', patch_path], cwd=component_path)
+
+    def _clean_submodules(self):
+        all_components = {self.snapshot['base']['name']: self.snapshot['base']}
+        for component in self.snapshot['components']:
+            all_components[component['name']] = component
+        for name in os.listdir(self.componentdir):
+            fullpath = os.path.join(self.componentdir, name)
+            relpath = os.path.relpath(fullpath, self.srcdir)
+            if all_components.has_key(name):
+                continue
+            deleted_name = os.path.join(self.srcdir, 'deleted-components')
+            if os.path.isdir(deleted_name):
+                shutil.rmtree(deleted_name)
+            run_sync(['git', 'rm', '--cached', fullpath])
+            run_sync(['git', 'config', '-f', '.git/config', '--remove-section', 'submodule.' + relpath])
+
+    def execute(self, argv):
+        parser = argparse.ArgumentParser(description=self.short_description)
+        parser.add_argument('components', nargs='*')
+
+        args = parser.parse_args(argv)
+
+        self.parse_config()
+        self.parse_snapshot()
+
+        if len(args.components) > 0:
+            components = args.components
+        else:
+            components = map(lambda x: x['name'], self.snapshot['components'])
+
+        self._ensure_submodule(self.snapshot['base'])
+        self._sync_submodule(self.snapshot['base'])
+        for component_name in components:
+            component = self.get_component(component_name)
+            self._ensure_submodule(component)
+            self._sync_submodule(component)
+
+        self._clean_submodules()
+        
+builtins.register(OstbuildSubmoduleSync)
diff --git a/src/ostbuild/pyostbuild/builtins.py b/src/ostbuild/pyostbuild/builtins.py
index a4d5cd4..9492c70 100755
--- a/src/ostbuild/pyostbuild/builtins.py
+++ b/src/ostbuild/pyostbuild/builtins.py
@@ -25,7 +25,7 @@ import json
 
 from . import ostbuildrc
 from . import fileutil
-from . import jsondb
+from . import buildutil
 from .ostbuildlog import log, fatal
 from .subprocess_helpers import run_sync, run_sync_get_output
 
@@ -63,6 +63,14 @@ class Builtin(object):
         else:
             return (None, None)
 
+    def _component_path(self, component):
+        component_path = os.path.join(self.componentdir, component['name'])
+        return os.path.relpath(component_path, self.srcdir)
+
+    def _component_abspath(self, component):
+        component_path = os.path.join(self.componentdir, component['name'])
+        return os.path.abspath(component_path)
+
     def get_component_from_cwd(self):
         cwd = os.getcwd()
         parent = os.path.dirname(cwd)
@@ -72,16 +80,10 @@ class Builtin(object):
     def parse_config(self):
         self.ostbuildrc = ostbuildrc
 
-        self.mirrordir = os.path.expanduser(ostbuildrc.get_key('mirrordir'))
-        if not os.path.isdir(self.mirrordir):
-            fatal("Specified mirrordir '%s' is not a directory" % (self.mirrordir, ))
         self.workdir = os.path.expanduser(ostbuildrc.get_key('workdir'))
         if not os.path.isdir(self.workdir):
             fatal("Specified workdir '%s' is not a directory" % (self.workdir, ))
 
-        self.snapshot_dir = os.path.join(self.workdir, 'snapshots')
-        self.patchdir = os.path.join(self.workdir, 'patches')
-
     def get_component_snapshot(self, name):
         found = False
         for content in self.active_branch_contents['contents']:
@@ -136,35 +138,6 @@ class Builtin(object):
     def get_expanded_component(self, name):
         return self.expand_component(self.get_component(name))
 
-    def get_prefix(self):
-        if self.prefix is None:
-            path = os.path.expanduser('~/.config/ostbuild-prefix')
-            if not os.path.exists(path):
-                fatal("No prefix set; use \"ostbuild prefix\" to set one")
-            f = open(path)
-            self.prefix = f.read().strip()
-            f.close()
-        return self.prefix
-
-    def create_db(self, dbsuffix, prefix=None):
-        if prefix is None:
-            target_prefix = self.get_prefix()
-        else:
-            target_prefix = prefix
-        name = '%s-%s' % (target_prefix, dbsuffix)
-        fileutil.ensure_dir(self.snapshot_dir)
-        return jsondb.JsonDB(self.snapshot_dir, prefix=name)
-
-    def get_src_snapshot_db(self):
-        if self._src_snapshots is None:
-            self._src_snapshots = self.create_db('src-snapshot')
-        return self._src_snapshots
-
-    def get_bin_snapshot_db(self):
-        if self._bin_snapshots is None:
-            self._bin_snapshots = self.create_db('bin-snapshot')
-        return self._bin_snapshots
-
     def init_repo(self):
         if self.repo is not None:
             return self.repo
@@ -174,27 +147,26 @@ class Builtin(object):
         else:
             self.repo = os.path.join(self.workdir, 'repo')
 
-    def parse_prefix(self, prefix):
-        if prefix is not None:
-            self.prefix = prefix
-
-    def parse_snapshot(self, prefix, path):
-        self.parse_prefix(prefix)
+    def parse_snapshot(self):
         self.init_repo()
-        if path is None:
-            latest_path = self.get_src_snapshot_db().get_latest_path()
-            if latest_path is None:
-                raise Exception("No source snapshot found for prefix %r" % (self.prefix, ))
-            self.snapshot_path = latest_path
-        else:
-            self.snapshot_path = path
+        cwd_path = os.path.join(os.getcwd(), 'manifest.json')
+        if not os.path.isfile(cwd_path):
+            raise Exception("No source snapshot found here; looking for %s" % (cwd_path, ))
+        self.snapshot_path = cwd_path
         self.snapshot = json.load(open(self.snapshot_path))
         key = '00ostbuild-manifest-version'
         src_ver = self.snapshot[key]
-        if src_ver != 0:
-            fatal("Unhandled %s version \"%d\", expected 0" % (key, src_ver, ))
-        if self.prefix is None:
-            self.prefix = self.snapshot['prefix']
+        if src_ver != 1:
+            fatal("Unhandled %s version \"%d\", expected 1" % (key, src_ver, ))
+        self.srcdir = os.getcwd()
+        self.prefix = self.snapshot['prefix']
+        self.componentdir = os.path.join(os.getcwd(), 'components')
+
+        components = map(lambda x: buildutil.resolve_component_meta(self.snapshot, x), self.snapshot['components'])
+        components = map(lambda x: self.expand_component(x), components)
+        self.snapshot['components'] = components
+        base_meta = buildutil.resolve_component_meta(self.snapshot, self.snapshot['base'])
+        self.snapshot['base'] = base_meta
 
     def parse_snapshot_from_current(self):
         if self.ostree_dir is None:
diff --git a/src/ostbuild/pyostbuild/git.py b/src/ostbuild/pyostbuild/git.py
new file mode 100755
index 0000000..3a60209
--- /dev/null
+++ b/src/ostbuild/pyostbuild/git.py
@@ -0,0 +1,61 @@
+# Copyright (C) 2011 Colin Walters <walters verbum org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+import os
+import re
+import urlparse
+import shutil
+import subprocess
+
+from .subprocess_helpers import run_sync_get_output, run_sync
+from .ostbuildlog import log, fatal
+
+class GitCheckout(object):
+    def __init__(self, path):
+        self.path = path
+        gitpath = os.path.join(self.path, '.git')
+        if not os.path.exists(gitpath):
+            raise ValueError("%s doesn't exist" % (gitpath, ))
+
+    def clean(self):
+        run_sync(['git', 'clean', '-d', '-f', '-x'], cwd=self.path)
+
+    def checkout(self, revision):
+        run_sync(['git', 'checkout', '-q', revision], cwd=self.path)
+
+    def get_head(self):
+        return run_sync_get_output(['git', 'rev-parse', 'HEAD'], cwd=self.path)
+
+    def fetch(self):
+        run_sync(['git', 'fetch'], cwd=self.path)
+
+    def submodule_update(self):
+        run_sync(['git', 'submodule', 'update'], cwd=self.path)
+
+    def rebase(self, revision):
+        run_sync(['git', 'rebase', revision], cwd=self.path)
+
+    def enumerate_submodules(self):
+        proc = subprocess.Popen(['git', 'submodule', 'status'],
+                                stdout=subprocess.PIPE, cwd=self.path)
+        for line in proc.stdout:
+            if not line.startswith(' '):
+                continue
+            (empty, csum, path, rest) = line.split(' ', 4)
+            yield (csum, path, rest)
+        proc.wait()
+
diff --git a/src/ostbuild/pyostbuild/main.py b/src/ostbuild/pyostbuild/main.py
index 8a0bf27..3677185 100755
--- a/src/ostbuild/pyostbuild/main.py
+++ b/src/ostbuild/pyostbuild/main.py
@@ -23,18 +23,15 @@ import argparse
 
 from . import builtins
 from . import builtin_build
-from . import builtin_checkout
 from . import builtin_deploy_root
 from . import builtin_deploy_qemu
-from . import builtin_git_mirror
-from . import builtin_import_tree
 from . import builtin_init
 from . import builtin_run_qemu
-from . import builtin_prefix
 from . import builtin_privhelper_deploy_qemu
 from . import builtin_privhelper_run_qemu
 from . import builtin_repoweb_json
-from . import builtin_resolve
+from . import builtin_submodule_sync
+from . import builtin_submodule_fetch
 from . import builtin_source_diff
 
 def usage(ecode):



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]