[ostree] ostbuild: Add source-diff builtin



commit 6d59b4077c384aa4080de25f821541fcd2017a33
Author: Colin Walters <walters verbum org>
Date:   Fri May 18 20:12:35 2012 -0400

    ostbuild: Add source-diff builtin
    
    OMG OMG OMG

 Makefile-ostbuild.am                           |    1 +
 src/ostbuild/pyostbuild/builtin_source_diff.py |  120 ++++++++++++++++++++++++
 src/ostbuild/pyostbuild/builtins.py            |   24 ++++-
 src/ostbuild/pyostbuild/main.py                |    1 +
 src/ostbuild/pyostbuild/vcs.py                 |    2 +-
 5 files changed, 141 insertions(+), 7 deletions(-)
---
diff --git a/Makefile-ostbuild.am b/Makefile-ostbuild.am
index a3b855c..f038569 100644
--- a/Makefile-ostbuild.am
+++ b/Makefile-ostbuild.am
@@ -37,6 +37,7 @@ pyostbuild_PYTHON =					\
 	src/ostbuild/pyostbuild/builtin_prefix.py	\
 	src/ostbuild/pyostbuild/builtin_resolve.py	\
 	src/ostbuild/pyostbuild/builtin_init.py	\
+	src/ostbuild/pyostbuild/builtin_source_diff.py	\
 	src/ostbuild/pyostbuild/builtins.py		\
 	src/ostbuild/pyostbuild/filemonitor.py		\
 	src/ostbuild/pyostbuild/fileutil.py		\
diff --git a/src/ostbuild/pyostbuild/builtin_source_diff.py b/src/ostbuild/pyostbuild/builtin_source_diff.py
new file mode 100755
index 0000000..ce81c4f
--- /dev/null
+++ b/src/ostbuild/pyostbuild/builtin_source_diff.py
@@ -0,0 +1,120 @@
+# 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.
+
+# ostbuild-compile-one-make wraps systems that implement the GNOME build API:
+# http://people.gnome.org/~walters/docs/build-api.txt
+
+import os,sys,stat,subprocess,tempfile,re,shutil
+import argparse
+from StringIO import StringIO
+import json
+
+from . import builtins
+from .ostbuildlog import log, fatal
+from . import vcs
+from .subprocess_helpers import run_sync, run_sync_get_output
+from . import buildutil
+
+class OstbuildSourceDiff(builtins.Builtin):
+    name = "source-diff"
+    short_description = "Show differences in source code between builds"
+
+    def __init__(self):
+        builtins.Builtin.__init__(self)
+
+    def _snapshot_from_rev(self, rev):
+        self.init_repo()
+        text = run_sync_get_output(['ostree', '--repo=' + self.repo,
+                                    'cat', rev, '/contents.json'],
+                                   log_initiation=False)
+        return json.loads(text)
+
+    def execute(self, argv):
+        parser = argparse.ArgumentParser(description=self.short_description)
+        parser.add_argument('--rev-from')
+        parser.add_argument('--rev-to')
+        parser.add_argument('--snapshot-from')
+        parser.add_argument('--snapshot-to')
+
+        args = parser.parse_args(argv)
+        self.parse_config()
+
+        to_snap = None
+        from_snap = None
+
+        if args.rev_to:
+            to_snap = self._snapshot_from_rev(args.rev_to)
+        if args.rev_from:
+            from_snap = self._snapshot_from_rev(args.rev_from)
+        if args.snapshot_from:
+            from_snap = json.load(open(args.snapshot_from))
+        if args.snapshot_to:
+            to_snap = json.load(open(args.snapshot_to))
+
+        if to_snap is None:
+            fatal("One of --rev-to/--snapshot-to must be given")
+        if from_snap is None:
+            if args.rev_to:
+                from_snap = self._snapshot_from_rev(args.rev_to + '^')
+            else:
+                fatal("One of --rev-from/--snapshot-from must be given")
+
+        diff_replace_re = re.compile(' [ab]')
+
+        for from_component in from_snap['components']:
+            name = from_component['name']
+            src = from_component['src']
+            (keytype, uri) = vcs.parse_src_key(src)
+            if keytype == 'local':
+                log("Component %r has local URI" % (name, ))
+                continue
+            mirrordir = vcs.ensure_vcs_mirror(self.mirrordir, keytype, uri, from_component['branch'])
+
+            to_component = self.find_component_in_snapshot(name, to_snap)
+            if to_component is None:
+                log("DELETED COMPONENT: %s" % (name, ))
+                continue
+
+            from_revision = from_component.get('revision')
+            to_revision = to_component.get('revision')
+            if from_revision is None:
+                log("From component %s missing revision" % (name, ))
+                continue
+            if to_revision is None:
+                log("From component %s missing revision" % (name, ))
+                continue
+
+            if from_revision != to_revision:
+                env = dict(os.environ)
+                env['LANG'] = 'C'
+                
+                spacename = ' ' + name
+
+                proc = subprocess.Popen(['git', 'diff', from_revision, to_revision],
+                                        env=env, cwd=mirrordir, stdout=subprocess.PIPE)
+                for line in proc.stdout:
+                    if (line.startswith('diff --git ')
+                        or line.startswith('--- a/')
+                        or line.startswith('+++ b/')
+                        or line.startswith('Binary files /dev/null and b/')):
+                        line = diff_replace_re.sub(spacename, line)
+                        sys.stdout.write(line)
+                    else:
+                        sys.stdout.write(line)
+                proc.wait()
+
+builtins.register(OstbuildSourceDiff)
diff --git a/src/ostbuild/pyostbuild/builtins.py b/src/ostbuild/pyostbuild/builtins.py
index e97c33c..db8b009 100755
--- a/src/ostbuild/pyostbuild/builtins.py
+++ b/src/ostbuild/pyostbuild/builtins.py
@@ -122,12 +122,22 @@ class Builtin(object):
         meta['config-opts'] = config_opts
         return meta
 
-    def get_component(self, name):
-        assert self.snapshot is not None
-        for component in self.snapshot['components']:
+    def find_component_in_snapshot(self, name, snapshot):
+        for component in snapshot['components']:
             if component['name'] == name:
                 return component
-        fatal("Couldn't find component '%s' in manifest" % (component_name, ))
+        return None
+
+    def get_component(self, name, in_snapshot=None):
+        if in_snapshot is None:
+            assert self.snapshot is not None
+            target_snapshot = self.snapshot
+        else:
+            target_snapshot = in_snapshot
+        component = self.find_component_in_snapshot(self, target_snapshot)
+        if component is None:
+            fatal("Couldn't find component '%s' in manifest" % (component_name, ))
+        return component
 
     def get_expanded_component(self, name):
         return self.expand_component(self.get_component(name))
@@ -161,7 +171,9 @@ class Builtin(object):
             self._bin_snapshots = self.create_db('bin-snapshot')
         return self._bin_snapshots
 
-    def _init_repo(self):
+    def init_repo(self):
+        if self.repo is not None:
+            return self.repo
         repo = ostbuildrc.get_key('repo', default=None)
         if repo is not None:
             self.repo = repo
@@ -178,7 +190,7 @@ class Builtin(object):
 
     def parse_snapshot(self, prefix, path):
         self.parse_prefix(prefix)
-        self._init_repo()
+        self.init_repo()
         if path is None:
             latest_path = self.get_src_snapshot_db().get_latest_path()
             if latest_path is None:
diff --git a/src/ostbuild/pyostbuild/main.py b/src/ostbuild/pyostbuild/main.py
index 4f6b27e..0adccd6 100755
--- a/src/ostbuild/pyostbuild/main.py
+++ b/src/ostbuild/pyostbuild/main.py
@@ -36,6 +36,7 @@ from . import builtin_prefix
 from . import builtin_privhelper_deploy_qemu
 from . import builtin_privhelper_run_qemu
 from . import builtin_resolve
+from . import builtin_source_diff
 
 def usage(ecode):
     print "Builtins:"
diff --git a/src/ostbuild/pyostbuild/vcs.py b/src/ostbuild/pyostbuild/vcs.py
index a6c11d8..1fa618f 100755
--- a/src/ostbuild/pyostbuild/vcs.py
+++ b/src/ostbuild/pyostbuild/vcs.py
@@ -84,7 +84,7 @@ def parse_src_key(srckey):
     if idx < 0:
         raise ValueError("Invalid SRC uri=%s" % (srckey, ))
     keytype = srckey[:idx]
-    if keytype not in ['git']:
+    if keytype not in ['git', 'local']:
         raise ValueError("Unsupported SRC uri=%s" % (srckey, ))
     uri = srckey[idx+1:]
     return (keytype, uri)



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