[ooo-build-commit] .: bin/fixguard.py bin/gob bin/gob.in configure.in
Thomas Klausner
tklausner at kemper.freedesktop.org
Tue Oct 5 01:17:59 PDT 2010
bin/fixguard.py | 2
bin/gob | 1070 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bin/gob.in | 1070 --------------------------------------------------------
configure.in | 1
4 files changed, 1071 insertions(+), 1072 deletions(-)
New commits:
commit 37efef7f873aaaae523d0fa84f96b8ebe42b96b6
Author: Thomas Klausner <wiz at NetBSD.org>
Date: Tue Oct 5 10:17:23 2010 +0200
Undo the remaining python changes.
diff --git a/bin/fixguard.py b/bin/fixguard.py
index 0451224..5381132 100755
--- a/bin/fixguard.py
+++ b/bin/fixguard.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
import sys
import re
import os
diff --git a/bin/gob b/bin/gob
new file mode 100755
index 0000000..292c17f
--- /dev/null
+++ b/bin/gob
@@ -0,0 +1,1070 @@
+#!/usr/bin/env python
+
+# gob.py - ooo-build to GIT conversion: dump gob branch description files
+# and create branched git
+#
+# Usage: python bin/gob --help
+
+import optparse
+import operator
+import os
+import re
+import sys
+import shutil
+
+class SystemFailed (Exception):
+ pass
+
+def log (s, threshold=1):
+ if options.verbose > threshold:
+ print >> sys.stderr, s
+
+def info (s):
+ log (s, threshold=0)
+
+def exception_string (exception=Exception ('no message')):
+ import traceback
+ return traceback.format_exc (None)
+
+def filter_out (predicate, lst):
+ return filter (lambda x: not predicate (x), lst)
+
+def makedirs (dir):
+ log ('mkdir %(dir)s' % locals ())
+ os.makedirs (dir)
+
+def symlink (src, dest):
+ log ('ln -s %(src)s %(dest)s' % locals ())
+ os.symlink (src, dest)
+
+def rename (src, dest):
+ log ('mv %(src)s %(dest)s' % locals ())
+ os.rename (src, dest)
+
+def rmdir (dir):
+ log ('rmdir %(dir)s' % locals ())
+ os.rmdir (dir)
+
+def system (command, raise_on_error=True):
+ if options.verbose > 1:
+ log ('executing: %(command)s' % locals ())
+ if options.verbose < 3:
+ command = '(%(command)s) > gob.log 2>&1' % locals ()
+ status = os.system (command)
+ if status and raise_on_error:
+ info (command)
+ info (file ('gob.log').read ())
+ raise SystemFailed ('Command failed: %(command)s' % locals ())
+ return status
+
+def read_pipe (command, raise_on_error=True):
+ log ('executing: %(command)s' % locals ())
+ if options.verbose < 3:
+ command = '(%(command)s) 2> gob.log' % locals ()
+ pipe = os.popen (command)
+ output = pipe.read ()
+ log ('pipe-output:\n%(output)s)s' % locals (), threshold=2)
+ if pipe.close () and raise_on_error:
+ info (command)
+ info (file ('gob.log').read ())
+ raise SystemFailed ('Pipe failed: %(command)s' % locals ())
+ return output
+
+def list_dirs (dir, allow_link=True):
+ return filter (lambda x: (os.path.isdir (os.path.join (dir, x))
+ and (allow_link
+ or not os.path.islink (os.path.join (dir, x)))),
+ os.listdir (dir))
+
+def find_file (root, path, name):
+ for dir in path:
+ file_name = os.path.abspath (os.path.join (root, dir, name))
+ if os.path.isfile (file_name):
+ return file_name
+ return None
+
+def _apply_patch (dir, patch):
+ system ('patch -l -p0 -d %(dir)s < %(patch)s' % locals ())
+
+def apply_patch (dir, patch):
+ if not options.split:
+ return _apply_patch (dir, patch)
+ apply_dir = os.path.join (dir, options.flat_apply_dir)
+ _apply_patch (apply_dir, patch)
+ for module in list_dirs (apply_dir, allow_link=False):
+ rename (os.path.join (apply_dir, module), os.path.join (dir, module))
+
+def get_srcpack2_dict ():
+ def modules_line (x):
+ e = x.split ("=")
+ return e[0], e[1].split (',')
+ return dict (map (modules_line, file (src_dir + 'bin/modules2.txt').readlines ()))
+
+def for_each (func, lst):
+ for i in lst:
+ func (i)
+
+def move (src):
+ src2 = get_srcpack2_dict ()
+ def move_pack (pack):
+ pack_dir = os.path.join (src, pack)
+ def move_module (module):
+ module_dir = src + '/' + module
+ pack_module_dir = pack_dir + '-/' + module
+ if os.path.exists (module_dir):
+ rename (module_dir, pack_module_dir)
+ makedirs (pack_dir + '-')
+ for_each (move_module, src2[pack])
+ rename (pack_dir + '-', pack_dir)
+ for_each (move_pack, src2.keys ())
+
+def move_back (src):
+ src2 = get_srcpack2_dict ()
+ def move_pack (pack):
+ pack_dir = os.path.join (src, pack)
+ def move_module (module):
+ print 'renaming:', module
+ module_dir = src + '/' + module
+ pack_module_dir = pack_dir + '-/' + module
+ if os.path.exists (pack_module_dir):
+ rename (pack_module_dir, module_dir)
+ else:
+ print 'no such dir:', pack_module_dir
+ rename (pack_dir, pack_dir + '-')
+ for_each (move_module, src2[pack])
+ rmdir (pack_dir + '-')
+ for_each (move_pack, src2.keys ())
+
+def setup_flat_apply_dir (src):
+ src2 = get_srcpack2_dict ()
+ apply_dir = os.path.join (src, options.flat_apply_dir)
+ shutil.rmtree (apply_dir, ignore_errors=True)
+ makedirs (apply_dir)
+ missing = ['mdbtools', 'libwpg', 'libwps', 'xalan']
+ for pack in src2.keys ():
+ for module in src2[pack]:
+ symlink (os.path.join ('..', '..', pack, module), os.path.join (apply_dir, module))
+ for pack in missing:
+ symlink (os.path.join ('..', '..', pack), os.path.join (apply_dir, pack))
+
+def patch_get_branch (patch):
+ patch_file = patch.file_name
+ if not patch_file:
+ return None
+
+ if 'vba' in options.dir_branch and int (options.milestone) > 19:
+ m = re.search ('(cws-scsheetprotection02|sc-autofilter-empty-nonempty|sc-copy-source-border|sc-datapilot|sc-move-from-origin|sc-paste-on-enter|sc-save-password-minlength|scroll-accel|xl-import-formradiobutton)', patch_file)
+ if m:
+ return 'vba'
+
+ # Prevent from going into ooxml
+ m = re.search ('(writerfilter-qnametostr-NOOPTFILES)', patch_file)
+ if m:
+ return m.group (1)
+
+ dir = os.path.basename (os.path.dirname (patch_file))
+ base = os.path.splitext (os.path.basename (patch_file))[0]
+
+ module_re = None
+ if not module_re:
+ modules = list_dirs (options.build_dir)
+ if options.split:
+ modules = list_dirs (os.path.join (options.build_dir, options.flat_apply_dir))
+ module_re = '|'.join (modules)
+
+ # Patches with a simple digit suffix are aggregated into one branch
+ if (not re.search ('%(module_re)s$|\d\d+$' % locals (), base)
+ and re.search ('\d$', base)):
+ base = re.sub ('-*\d$', '', base)
+
+ # Patches in a separated may be aggregated into one branch
+ if dir in options.dir_branch:
+ return dir
+
+ # Pathes with a branch_prefix are aggregated into one branch
+ branch_prefix = [
+ 'cjk-character-units',
+ 'cws-layoutdialogs',
+ 'cws-scsheetprotection02',
+ 'emf+',
+ 'fpicker-kde',
+ 'jvmfwk-gij',
+ 'lockfile',
+ 'mono',
+ 'sal-strintern-speed',
+ 'sc-dataform',
+ 'sc-datapilot',
+ 'speed-configmgr',
+ 'svg-import',
+ 'system-lpsolve',
+ 'tools-urlobj-smb-scheme',
+ 'transogl',
+ 'unittesting',
+ 'unxsplash',
+ 'vba',
+ 'wpgimporter',
+ 'writerfiltery'
+ ]
+
+ branch_prefix_re = '^(' + '|'.join (branch_prefix).replace ('+', '\+') + ')'
+ m = re.search (branch_prefix_re, base)
+ if m:
+ def assert_dir_group (m, s):
+ return s in options.dir_branch or m.group (1) != s
+ if (assert_dir_group (m, 'vba')
+ and assert_dir_group (m, 'emf+')
+ and assert_dir_group (m, 'unittesting')):
+ return m.group (1)
+
+ # Some patches are declared in the middle of a branch [another
+ # series of patches that form a branch] which depends on that
+ # patch, but have derogatory naming. These patches must be
+ # categorised explicitly. The ASSIMILATE warning helps to detect
+ # these.
+ if 'emf+' in options.dir_branch and re.search ('^(cairocanvas-alpha-pixmap-rewrite|vcl-grey-alpha-unix-sal-bitmap)', base):
+ return 'emf+'
+
+ if 'ooxml' in options.dir_branch and re.search ('^(win32-installer-register-moox-types)', base):
+ return 'ooxml'
+
+ if 'vba' in options.dir_branch and re.search ('^(default-autotext-and-form-name|sc-toggle-merge-center)', base):
+ return 'vba'
+
+ if re.search ('^(fix-linkoo|linkoo-)', base):
+ return 'linkoo'
+
+ if re.search ('^(fpicker-common-scp2)', base):
+ return 'fpicker-kde'
+
+ # Remove workspace and milestone suffixes
+ workspace = options.workspace
+ milestone = options.milestone
+ base = re.sub ('-%(workspace)s' % locals (), '', base)
+ base = re.sub ('-m%(milestone)s' % locals (), '', base)
+
+ # Patches with a -localize suffix are aggregated into one branch
+ base = re.sub ('-localize$' % locals (), '', base)
+
+ # Patches with a module suffix are aggregated into one branch
+ base = re.sub ('-(%(module_re)s)$' % locals (), '', base)
+
+ # git does not like dots in branch names
+ base = base.replace('.','-')
+
+ return base
+
+# Hard handy work for m19 gets quickly bit rotten
+# Use patch dependency calculation instead
+manual_m19_branch_dependencies = {
+ 'buildfix-layoutdialogs': ['cws-layoutdialogs'],
+ 'cairocanvas-fix-image-cache': ['cairo'],
+ 'cws-scsheetprotection02': ['sc-datapilot', 'sc-paste-on-enter'],
+ 'emf+': ['link-as-needed'],
+ 'forms-radio-button-group-names': ['form-control-visibility'],
+ 'layout-plugin': ['cws-layoutdialogs'],
+ 'layout-tab': ['layout-plugin'],
+ 'linkwarn-svtools-miscopts-bits': ['novell-win32-odma'],
+ 'ooo59127.vcl.honourcairofont': ['ooo64508.vcl.honourfontconfighinting'],
+ 'oosplash-etc-openoffice-sofficerc': ['unxsplash'],
+ 'ooxml': ['lwp-filter-component'],
+ 'sc-copy-on-merged-cells': ['sc-dataform'],
+ 'sc-dataform': ['sc-hrc-ooo-build-resources'],
+ 'sc-datapilot': ['sc-dataform'],
+ 'sc-dp-gridlayout': ['sc-datapilot'],
+ 'sc-export-shape-hlink-bindings': ['sc-export-shape-macro-bindings'],
+ 'sc-simple-sort-include-format-header': ['sc-natural-sort'],
+ 'sc-toggle-merge-center': ['vba'],
+ 'sfx2-pre-and-postprocess-crash-fix': ['sfx2-pre-and-postprocess-during-save-load'],
+ 'sfx2-pre-and-postprocess-during-save-load': ['sfx2-remove-check-update-on-fileload'],
+ 'speed-bdirect': ['speed-symbolic-functions'],
+ 'speed-store-lck': ['store-core'],
+ 'static-libs-use-_pic': ['system-lpsolve'],
+ 'ui-desktop-integration': ['linkwarn-svtools-miscopts-bits'],
+ 'unittesting': ['tools-qa-urlobj-unittest', 'gnome-vfs-late-init'],
+ 'vba': ['cws-npower10', 'cws-pflin10', 'cws-npower11'],
+ 'vcl-linking-randr': ['autocorrect-accidental-caps-lock', 'internal-mesa-headers'],
+ 'wpgimporter': ['wpsimport'],
+}
+
+def range_union (a, b, fuzz=0):
+ u = (max (a[0], b[0]) - fuzz, min (a[1], b[1]) + fuzz, a[2], b[2])
+ if u[0] > u[1]:
+ return None
+ return u
+
+class File:
+ def __init__ (self, s):
+ self.string = s
+ self.ranges = None
+ self.name = None
+ if self.string.find ('\n+++ ') >= 0:
+ self.name = re.search ('\n[+]{3}\s+([.]/)?([^\s]+)', self.string).group (2)
+ def __repr__ (self):
+ return '<File: %(name)s>' % self.__dict__
+ def get_ranges (self):
+ if not self.ranges:
+ self.numbers = re.findall ('\n(@@ -(\d+),(\d+) [+](\d+),(\d+) @@(.|\n[^@])*)', self.string)
+ self.ranges = map (lambda x: (min (int (x[1]), int (x[3])), max (int (x[1]) + int (x[2]), int (x[3]) + int (x[4])), x[0][:160]), self.numbers)
+ return self.ranges
+
+def patch_depend (p, q):
+ files = []
+ for file_name in p.files.keys ():
+ if file_name in q.files.keys ():
+ for a in p.files[file_name].get_ranges ():
+ for b in q.files[file_name].get_ranges ():
+ union = range_union (a, b, int (options.fuzz))
+ if union:
+ return union
+ return False
+
+def patch_get_dependencies (patches, patch):
+ dependencies = ['pristine']
+ for p in patches:
+ if p == patch:
+ break
+ if patch_depend (patch, p):
+ dependencies += [p.name]
+ return dependencies
+
+def branch_get_dependencies (branches, patches, branch):
+ patch_dependencies = {}
+ patch_overlaps = []
+ first_patch = None
+ for patch in patches:
+ if patch in branches[branch]:
+ first_patch = patch
+ break
+ last_patch = None
+ for patch in reversed (patches):
+ if patch in branches[branch]:
+ last_patch = patch
+ break
+ for patch in branches[branch]:
+ assimilate = False
+ for p in patches:
+ if p == last_patch:
+ name = p.name
+ break
+ if p == first_patch:
+ name = p.name
+ # We cannot have a branch pre-depend on a patch/branch
+ # that does not exist yet. FIXME: if it is really
+ # needed, it should be auto-assimilated by the branch.
+ # This is now done manually in patch_get_branch ().
+ assimilate = True
+ o = patch_depend (patch, p)
+ if assimilate and o and p not in branches[branch]:
+ name = p.name
+ ab = patch_get_branch (p)
+ print 'ASSIMILATE[%(branch)s]: %(name)s [%(ab)s]' % locals ()
+ continue
+ if o:
+ patch_dependencies[p] = p
+ patch_overlaps += [o]
+ branch_dependencies = {}
+ for patch in patch_dependencies.values ():
+ b = patch_get_branch (patch)
+ if b != branch:
+ branch_dependencies[b] = b
+ if not branch_dependencies:
+ return ['pristine']
+ return branch_dependencies.values ()
+
+# No overrides are necessary when using fuzz >= 40
+branch_override_dependencies = {
+ }
+
+def branch_get_dependencies_with_override (branches, patches, branch):
+ return branch_override_dependencies.get (branch, branch_get_dependencies (branches, patches, branch))
+
+GitFailed = SystemFailed
+
+gitignores = '''
+*-
+*-HEAD
+*-git
+*-patched
+*-pristine
+*.bak
+*.cxx-*
+*.deps
+*.git
+*.hxx-*
+*.log
+*.orig
+*.patched
+*.pristine
+*.pyc
+*.rej
+*~
+.\#*
+/Linux*Env.Set*
+/bootstrap
+/makefile.mk
+/solver
+CVS
+TAGS
+\#*
+xxx-have-in-patches-now:localize.sdf
+unxlng*.pro
+autom4te.cache/
+config.log
+config.parms
+config.status
+configure
+set_soenv
+tmon.out
+visibility.cxx
+visibility.s
+warn
+default_images/introabout/intro-save.bmp
+dmake/Makefile
+dmake/config.h
+dmake/config.log
+dmake/config.status
+dmake/dmake
+dmake/*.o
+dmake/dmakeroot.h
+dmake/stamp-h1
+dmake/startup/Makefile
+dmake/startup/config.mk
+dmake/startup/unix/Makefile
+dmake/startup/unix/cygwin/Makefile
+dmake/startup/unix/linux/Makefile
+dmake/startup/unix/macosx/Makefile
+dmake/startup/unix/solaris/Makefile
+dmake/startup/unix/sysvr4/Makefile
+dmake/startup/winnt/Makefile
+dmake/startup/winnt/mingw/Makefile
+dmake/startup/winnt/msvc6/Makefile
+dmake/tests/Makefile
+dmake/unix/.dirstamp
+instsetoo_native/res/banner_nld.bmp
+instsetoo_native/res/banner_ooop.bmp
+instsetoo_native/res/nologoinstall_nld.bmp
+instsetoo_native/res/nologoinstall_ooop.bmp
+instsetoo_native/util/OpenOffice
+sd/xml/transitions-ogl.xml
+setup_native/source/win32/nsis/ooobanner_nld.bmp
+setup_native/source/win32/nsis/ooobanner_ooop.bmp
+setup_native/source/win32/nsis/ooobitmap_nld.bmp
+setup_native/source/win32/nsis/ooobitmap_ooop.bmp
+setup_native/source/win32/nsis/ooosetup_nld.ico
+solenv/unxlng*/
+svx/res
+'''
+keep = '''
+default_images/introabout/intro-save.bmp
+default_images/introabout/intro.bmp
+default_images/svx/res/openabout_ark.png
+default_images/svx/res/openabout_translateorgza.png
+default_images/sw/res/go-oo-team.png
+'''
+
+def create_gitignores (dir):
+ for i in filter_out (operator.not_, gitignores.split ('\n')):
+ if options.split:
+ i = i.replace ('/bootstrap', '/bootstrap/bootstrap')
+ if i[0] == '/':
+ file (dir + '/.gitignore', 'a').write (i + '\n')
+ else:
+ slash = ''
+ if i[-1] == '/':
+ i = i[:-1]
+ slash = '/'
+ file (dir + '/' + os.path.dirname (i) + '/.gitignore', 'a').write (os.path.basename (i) + slash + '\n')
+
+class Setup:
+ string = None
+ vars = {}
+ def __init__ (self, file_name='config.log'):
+ if not self.string and os.path.exists (file_name):
+ self.string = file (file_name).read ()
+ def get (self, key, default=None):
+ return self.vars.get (key, self.read_ (key, default))
+ def read_ (self, key, default):
+ m = re.search ('''%(key)s=['"*]([^*"']*)''' % locals (), self.string)
+ if m:
+ self.vars[key] = m.group (1)
+ else:
+ self.vars[key] = default
+ return self.vars[key]
+
+def get_svn_revision ():
+ return re.search ('\nRevision: ([0-9]+)', read_pipe ('svn info')).group (1)
+
+def get_git_committish ():
+ return re.search ('([^ ]+)', read_pipe ('git log --pretty=oneline -1')).group (1)
+
+class Git:
+ def __init__ (self, dir, patched, clean=False):
+ self.dir = dir
+ self.patched = patched
+ self.scratch = 'work/scratch'
+ self.workspace = options.workspace
+ self.milestone = options.milestone
+ self.pristine = 'upstream/%(workspace)s-m%(milestone)s' % self.__dict__
+ self.commits = {}
+ self.log = {}
+ if not os.path.exists (self.dir):
+ drink = Setup ().get ('DRINK', 'tea')
+ info ('Unpacking source tree - [ go and have some %(drink)s ] ...' % locals ())
+ system ('cd bin && ./unpack')
+ create_gitignores (dir)
+ if options.split:
+ move (self.dir)
+ setup_flat_apply_dir (self.dir)
+ self.system ('touch unpack')
+ if not os.path.isdir (dir + '/.git/refs'):
+ drink = Setup ().get ('DRINK')
+ info ('Creating GIT archive - [ go and have some %(drink)s ] ...' % locals ())
+ self.system ('git init')
+ #svn_revision = get_svn_revision ()
+ #self.commit ('Initial svn:r%(svn_revision)s unpatched.' % locals ())
+ git_committish = get_git_committish ()
+ self.commit ('Initial ooo-build: %(git_committish)s unpatched.' % locals ())
+ self.system ('git branch %(pristine)s' % self.__dict__)
+ self.system ('git tag gob-%(workspace)s-%(milestone)s %(pristine)s' % self.__dict__)
+ self.system ('git branch pristine')
+ self.system ('git gc')
+ if clean:
+ if self.is_modified ():
+ self.system ('git reset --hard HEAD')
+ self.system ('git clean -df')
+ if self.has_branch (self.patched):
+ self.checkout (self.patched)
+ else:
+ self.system ('git checkout -b %(patched)s pristine' % self.__dict__)
+ if self.has_branch (self.scratch):
+ self.system ('git branch -D %(scratch)s' % self.__dict__)
+ def pipe (self, command, raise_on_error=True):
+ dir = self.dir
+ return read_pipe ('cd %(dir)s && %(command)s' % locals (), raise_on_error)
+ def system (self, command, raise_on_error=True):
+ dir = self.dir
+ return system ('cd %(dir)s && %(command)s' % locals (), raise_on_error)
+ def get_branches (self):
+ return filter_out (operator.not_,
+ self.pipe ('git branch')
+ .replace ('*', '')
+ .replace (' ', '').split ('\n'))
+ def get_log (self, branch=''):
+ commit = self.get_current_commit (branch)
+ self.log[commit] = self.log.get (commit, self.pipe ('git log --pretty=oneline %(branch)s --' % locals ()))
+ return self.log[commit]
+ def get_current_commit (self, branch=''):
+ if not branch:
+ branch = 'HEAD'
+ return self.pipe ('git rev-parse %(branch)s' % locals ())[:-1]
+ def get_commit (self, patch):
+ if not self.commits:
+ log = self.get_log (self.patched)
+ def grok_log_line (s):
+ m = re.match ('([^ ]+) Apply.*/([^/]+[.](diff|patch))', s)
+ if not m:
+ info ('Skipping line:%(s)s:' % locals ())
+ return None, None
+ return m.group (2), m.group (1)
+ self.commits = dict (map (grok_log_line, log.split ('\n')[:-2]))
+ return self.commits.get (patch, None)
+ def commit (self, message):
+ self.system ('git add .')
+ self.system ('git add -u .')
+ self.system ('''git commit -m '%(message)s' ''' % locals ())
+ def is_modified (self):
+ return re.sub ('# On branch.*\nnothing to commit \(working directory clean\)\n', '',
+ self.pipe ('git status', raise_on_error=False))
+ def assert_clean (self):
+ dir = self.dir
+ pending = self.is_modified ()
+ if pending:
+ raise GitFailed ('working directory unclean: %(dir)s\n%(pending)s' % locals ())
+ def checkout (self, branch):
+ if not self.is_on_branch (branch):
+ self.system ('git checkout %(branch)s' % locals ())
+ def get_current_branch (self):
+ return self.pipe ('git symbolic-ref HEAD', raise_on_error=False)[len ('refs/heads/'):-1]
+ def is_on_branch (self, branch):
+ return branch == self.get_current_branch ()
+ def has_branch (self, branch):
+ return branch in self.get_branches ()
+ def apply_patch (self, branches, patches, patch):
+ branch = patch_get_branch (patch)
+ info ('Applying patch[%(branch)s]: ' % locals () + patch.name)
+ patched = self.get_current_branch ()
+ apply_patch (self.dir, patch.file_name)
+ base = os.path.basename (patch.file_name)
+ self.commit ('Apply %(base)s.' % locals ())
+ if options.milestone == '19':
+ dependencies = manual_m19_branch_dependencies.get (branch, ['pristine'])
+ else:
+ dependencies = branch_get_dependencies_with_override (branches, patches, branch)
+ if not self.has_branch (branch):
+ if not options.topgit:
+ base_depend = dependencies[0]
+ self.system ('git checkout -b %(branch)s %(base_depend)s' % locals ())
+ for dependency in dependencies[1:]:
+ self.system ('git rebase %(dependency)s' % locals ())
+ else:
+ depend_str = ' '.join (dependencies)
+ self.system ('tg create %(branch)s %(depend_str)s' % locals ())
+ self.system ('git commit -am "topgit branch info %(branch)s"' % locals ())
+ else:
+ self.checkout (branch)
+ log = self.get_log (patched)
+ commit = log[:log.index (' ')]
+ self.system ('git cherry-pick -x %(commit)s' % locals ())
+ def before_ (self):
+ self.assert_clean ()
+ self.system ('git checkout -b %(scratch)s %(patched)s' % self.__dict__)
+ def after_ (self):
+ self.system ('git push . %(scratch)s:%(patched)s' % self.__dict__)
+ self.checkout (self.patched)
+ self.system ('git branch -D %(scratch)s' % self.__dict__)
+ def pick_patch (self, patch, commit):
+ branch = patch_get_branch (patch)
+ info ('Picking patch[%(branch)s]: ' % locals () + patch.name)
+ self.system ('git cherry-pick -x %(commit)s' % locals ())
+ def add_patch (self, branches, patches, patch):
+ if patch.name in self.get_log ():
+ info ('patch already applied, skipping: ' + patch.name)
+ return
+ if file (patch.file_name).read ().find ('\n+++ ') == -1:
+ info ('patch is empty, skipping: ' + patch.name)
+ return
+ commit = None
+ branch = patch_get_branch (patch)
+ if self.has_branch (branch):
+ name = patch.name.replace ('+', '\+')
+ m = re.search ('(^|\n)([^\s]+)\s+.*(\s|/)%(name)s' % locals (), self.get_log (branch))
+ if m:
+ commit = m.group (2)
+ self.before_ ()
+ if commit:
+ self.pick_patch (patch, commit)
+ else:
+ self.apply_patch (branches, patches, patch)
+ self.after_ ()
+ def dump_gob (self, branches, patches, branch):
+ gob_dir = self.dir + '/.git/refs/gob'
+ if not os.path.exists (gob_dir):
+ makedirs (gob_dir)
+ branch_patches = branches.get (branch, [])
+ if not branch_patches:
+ return
+ owner = ''
+ for patch in branch_patches:
+ owner = patch.owner
+ if owner:
+ break
+ issues = []
+ for patch in branch_patches:
+ issues += patch.issues
+ issue_string = ', '.join (issues)
+ dependencies = filter (lambda x: x != 'pristine', branch_get_dependencies (branches, patches, branch))
+ dependencies_string = ', '.join (dependencies)
+ commit = self.get_current_commit ()
+ gob_file_name = os.path.join (gob_dir, branch)
+ info ('Writing: ' + gob_file_name)
+ file (gob_file_name, 'w').write ('''%(commit)s
+state: stable
+issue: %(issue_string)s
+owner: %(owner)s
+depend: %(dependencies_string)s
+''' % locals ())
+
+class Patch:
+ def __init__ (self, file_name):
+ self.file_name = file_name
+ if self.file_name:
+ self.set_files ()
+ self.file_name = None
+ def set_files (self):
+ self.files = dict (map (lambda x: (x.name, x), map (File, ('\n' + file (self.file_name).read ()).split ('\n---')[1:])))
+ def __repr__ (self):
+ return '<Patch: ' + str (map (str, self.files.values ())) + ' >'
+
+class Apply_patch (Patch):
+ def __init__ (self, s, section, owner, issue):
+ Patch.__init__ (self, None)
+ self.string = s
+ self.section = section
+ self.owner = owner
+ m = re.search (', (\w\w+)', self.string)
+ if m:
+ self.owner = m.group (1)
+ m = re.match ('^\s*(([^#\s].*).(diff|patch))(.*)', self.string)
+ self.name = m.group (1)
+ self.base = m.group (2)
+ self.issues = map (lambda x: x[0], re.findall ('((i|n)#[0-9]+)', self.string))
+ if issue:
+ self.issues.append (issue)
+ def __repr__ (self):
+ return '<Patch: %(file_name)s [%(section)s] %(owner)s %(issues)s>' % self.__dict__
+ def set_file_name (self, dir, path):
+ self.file_name = find_file (dir, path, self.name)
+ self.set_files ()
+ return self
+
+class Section:
+ def __init__ (self, s):
+ self.string = s
+ m = re.match ('[[\s]*(.*[^\s])\s*\]', self.string)
+ self.tag = m.group (1).replace (' ', '')
+ self.name = re.sub ('[^\w].*', '', self.tag)
+ m = re.search ('\n(SectionOwner)\s*=>\s*(.*[^\s])', self.string)
+ self.owner = ''
+ if m:
+ self.owner = m.group (2)
+ m = re.search ('\n(SectionIssue)\s*=>\s*(.*[^\s])', self.string)
+ self.issue = ''
+ if m:
+ self.issue = m.group (2)
+ def __repr__ (self):
+ return '<Section: %(tag)s %(owner)s %(issue)s>' % self.__dict__
+ def get_patches (self):
+ def create_patch (s):
+ return Apply_patch (s[0], self.tag, self.owner, self.issue)
+ return map (create_patch, re.findall ('\n\s*([^#\s].*.(diff|patch).*)', self.string))
+
+class Apply:
+ def __init__ (self, apply_file, workspace, milestone):
+ self.workspace = workspace
+ self.milestone = milestone
+ self.string = file (apply_file).read ()
+ first_section = self.string.index ('\n[')
+ self.distros_string = self.string[:first_section]
+ self.sections_string = self.string[first_section:]
+ self.path = re.search ('\nPATCHPATH=(.*)', self.string).group (1).split (':')
+ self.distro = {}
+ self.master = {}
+ self.distros_string = re.sub ('\s*\\\s*\n\s*', '', self.distros_string)
+ for distro in re.findall ('\n\s*([^#=\s:]+)\s*:\s*(.*)', self.distros_string):
+ lst = distro[1].replace (' ', '').split (',')
+ expanded = []
+ for i in lst:
+ if i in self.master.keys ():
+ del self.master[i]
+ expanded += self.distro.get (i, [i])
+ self.master[distro[0]] = self.distro[distro[0]] = expanded
+ # convenience: add sections as distro
+ #self.distro.update (dict (map (lambda x: (x.name, x.name), self.get_sections ())))
+ def get_section_strings (self):
+ return map (lambda x: '[' + x, self.sections_string.split ('\n[')[1:])
+ def get_sections (self):
+ return map (Section, self.get_section_strings ())
+ def get_distro (self, distro_name):
+ def section_in_distro (section):
+ if distro_name not in self.distro.keys ():
+ return distro_name == section.name
+ m = re.search ('(\w+).*(<=|<|==|!=|>=|>)%(workspace)s-m([0-9]+)'
+ % self.__dict__, section.tag)
+ if m:
+ name = m.group (1)
+ if not name in self.distro[distro_name]:
+ return False
+ left_milestone = self.milestone
+ operator = m.group (2)
+ right_milestone = int (m.group (3))
+ return eval ('%(left_milestone)s %(operator)s %(right_milestone)s' % locals ())
+ else:
+ return section.tag in self.distro[distro_name]
+ return filter (section_in_distro, self.get_sections ())
+
+class Command:
+ def __init__ (self, apply, options):
+ self.options = options
+ self.apply = apply
+ self.patches_ = []
+ self.branches_ = {}
+ def patches (self):
+ '''list patches'''
+ print '\n'.join (map (str, self.get_patches ()))
+ def sections (self):
+ '''list sections'''
+ print '\n'.join (map (str, self.get_sections ()))
+ def distros (self):
+ '''list distros'''
+ print '\n'.join (map (str, self.apply.distro.keys ()))
+ def masters (self):
+ '''list masters'''
+ print '\n'.join (map (str, self.apply.master.keys ()))
+ def branches (self):
+ '''list branches'''
+ print '\n'.join (map (str, self.get_branches ().keys ()))
+ def get_branches (self):
+ if not self.branches_:
+ for patch in self.get_patches ():
+ branch = patch_get_branch (patch)
+ self.branches_[branch] = self.branches_.get (branch, []) + [patch]
+ return self.branches_
+ def dump_gobs (self):
+ '''dump gob files'''
+ branches = self.get_branches ()
+ patches = self.get_patches ()
+ git = Git (self.options.build_dir, self.options.patched)
+ for branch in git.get_branches ():
+ git.dump_gob (branches, patches, branch)
+ def checkout (self):
+ '''checkout patched ('master') branch'''
+ git = Git (self.options.build_dir, self.options.patched)
+ def git_export (self):
+ '''export to GIT with branches'''
+ git = Git (self.options.build_dir, self.options.patched, clean=True)
+ patches = self.get_patches ()
+ branches = self.get_branches ()
+ for patch in self.get_patches ():
+ git.add_patch (branches, patches, patch)
+ git.system ('git gc')
+ def get_patches_for_distro (self, distro):
+ patches = reduce (operator.add, map (lambda section: section.get_patches (), self.get_sections_for_distro (distro)))
+ for patch in patches:
+ patch.set_file_name (self.options.apply_dir, self.apply.path)
+ return patches
+ def get_patches (self):
+ if not self.patches_:
+ self.patches_ = reduce (operator.add, map (self.get_patches_for_distro, self.options.distros))
+ return self.patches_
+ def get_sections_for_distro (self, distro):
+ return self.apply.get_distro (distro)
+ def get_sections (self):
+ return reduce (operator.add, map (self.get_sections_for_distro, self.options.distros))
+ def prepare (self):
+ '''prepare ooo-build dir for use with GIT'''
+ git = Git (self.options.build_dir, self.options.patched)
+ def postpare (self):
+ '''update ooo-build dir GIT after patching'''
+ git = Git (self.options.build_dir, self.options.patched)
+ #svn_revision = get_svn_revision ()
+ #git.commit ('Update to svn:r%(svn_revision)s patched.' % locals ())
+ git_committish = get_git_committish ()
+ git.commit ('Update to ooo-build: %(git_committish)s patched.' % locals ())
+ git.system ('git rebase patched')
+ def dependencies (self):
+ '''list branch dependencies'''
+ patches = self.get_patches ()
+ branches = self.get_branches ()
+ independent = 0
+ for branch in branches:
+ dependencies = sorted (branch_get_dependencies (branches, patches, branch))
+ if dependencies == ['pristine']:
+ independent += 1
+ print 'BRANCH:', branch, '->', dependencies
+ print 'INDEPENDENT:', independent
+ def patch_dependencies (self):
+ '''list patch dependencies'''
+ branches = self.get_branches ()
+ patches = self.get_patches ()
+ for patch in patches:
+ branch = patch_get_branch (patch)
+ name = patch.name
+ print 'PATCH[%(branch)s]: %(name)s -> ' % locals (), patch_get_dependencies (patches, patch)
+ def bump (self):
+ '''bump BRANCH TAG-NAME - bump current branch (BRANCH=new upstream)'''
+ if len (self.options.arguments) != 2:
+ print 'Usage: gob bump BRANCH TAG-NAME'
+ print 'BRANCH: new upstream'
+ print 'Example:'
+ print ' gob bump upstream/dev300-m21 my-21-update'
+ sys.exit (2)
+ branch = self.options.arguments[0]
+ tag = self.options.arguments[1]
+ git_dir = self.options.build_dir
+ system ('cd %(git_dir)s && gob-bump %(branch)s %(tag)s' % locals ())
+ def update (self):
+ '''update BRANCH - update current branch (BRANCH='master')'''
+ if len (self.options.arguments) != 1:
+ print 'Usage: gob update BRANCH'
+ print '''BRANCH: the 'master' branch'''
+ print 'Example: '
+ print ' gob update distro/SUSE'
+ sys.exit (2)
+ branch = self.options.arguments[0]
+ git_dir = self.options.build_dir
+ system ('cdi %(git_dir)s && gob-update %(branch)s' % locals ())
+ def reset (self):
+ '''reset - set GIT tree to pristine and remove all branches'''
+ git = Git (self.options.build_dir, self.options.patched)
+ git.system ('git checkout -f %(patched)s' % git.__dict__)
+ git.system ('git reset --hard pristine')
+ git.system ('git clean -df')
+ git.system ('rm -rf .git/refs/top-bases')
+ cmd = 'xargs git branch -D'
+ if options.split:
+ git.system ('''git branch | grep -Ev '/|master|patched|pristine|upstream|%(patched)s' | xargs tg delete -f ''' % git.__dict__)
+ git.system ('''git branch | grep -Ev '/|master|patched|pristine|upstream|%(patched)s' | xargs git branch -D''' % git.__dict__)
+ def patch_depend (self):
+ '''patch-depend PATCH-1 PATCH-2 - show overlap between patches'''
+ if len (self.options.arguments) != 2:
+ print 'Usage: patch-depend PATCH-1 PATCH-2'
+ sys.exit (2)
+ union = patch_depend (Patch (self.options.arguments[0]), Patch (self.options.arguments[1]))
+ if union:
+ print union[0], '--', union[1]
+ print union[2]
+ print '<<<<<<<<<<<<<<<<<<<<<<<<<=========================>>>>>>>>>>>>>>>>>>>>>>>>>'
+ print union[3]
+ sys.exit (1)
+ def statistics (self):
+ ### not advertised
+ ### show some statistics on dependensies
+ patches = self.get_patches ()
+ branches = self.get_branches ()
+ full_match = 0
+ match = 0
+ fail = 0
+ extra = 0
+ independent = 0
+ for branch in branches:
+ manual_dependencies = sorted (manual_m19_branch_dependencies.get (branch, ['pristine']))
+ auto_dependencies = sorted (branch_get_dependencies (branches, patches, branch))
+ missing = False
+ for m in manual_dependencies:
+ if m != 'pristine' and not m in auto_dependencies:
+ missing = True
+ break
+ if missing:
+ fail += 1
+ print
+ print 'BRANCH:', branch
+ print 'MANUAL:', manual_dependencies
+ print 'AUTO:', auto_dependencies
+ #dependencies 'OVERLAPS:', overlaps
+ if auto_dependencies == ['pristine']:
+ independent += 1
+ elif auto_dependencies == manual_dependencies:
+ full_match += 1
+ elif manual_dependencies == ['pristine']:
+ extra += 1
+ #print 'BRANCH:', branch
+ #print 'EXTRA:', auto_dependencies
+ elif not missing:
+ match += 1
+ print
+ print 'FAIL:', fail
+ print 'FULL_MATCH:', full_match
+ print 'MATCH:', match
+ print 'EXTRA:', extra
+ print 'INDEPENDENT:', independent
+ def move (self):
+ move (options.build_dir)
+ setup_flat_apply_dir (options.build_dir)
+ def move_back (self):
+ move_back (options.build_dir)
+
+def get_cli_parser ():
+ p = optparse.OptionParser ()
+
+ p.usage = '%prog [OPTION]... COMMAND\n\nCommands:\n'
+ d = Command.__dict__
+ commands = [(k, d[k].__doc__) for k in d.keys ()
+ if d[k].__doc__ and type (d[k]) == type (lambda x: x)]
+ commands.sort ()
+
+ global src_dir
+ src_dir = ''
+ if not os.path.exists ('patches'):
+ src_dir = '../'
+ os.environ['PATH'] = src_dir + '/bin:' + os.environ['PATH']
+
+ for (command, doc) in commands:
+ p.usage += ' %s - %s\n' % (re.sub ('_', '-', command), doc)
+
+ def get (option):
+ return p.get_option ('--' + option.replace ('-', '_')).default
+
+ setup_workspace, setup_milestone = Setup ().get ('CVSTAG', 'dev300-m19').split ('-m')
+
+ p.add_option ('--workspace',
+ dest='workspace',
+ default=setup_workspace,
+ metavar='STRING',
+ help='set master workspace')
+ p.add_option ('--milestone',
+ dest='milestone',
+ default=setup_milestone,
+ metavar='STRING',
+ help='set milestone')
+ p.add_option ('--distro',
+ action='append',
+ dest='distros',
+ default=[],
+ metavar='DISTRO',
+ help='add distribution')
+ p.add_option ('--build-dir',
+ default=src_dir + 'build/' + get ('workspace') + '-m' + get ('milestone'),
+ dest='build_dir',
+ metavar='DIR',
+ help='build (/git) directory')
+ p.add_option ('--apply-dir',
+ default=src_dir + 'patches/' + get ('workspace'),
+ dest='apply_dir',
+ metavar='DIR',
+ help='directory with APPLY file')
+ p.add_option ('--patched',
+ default='patched',
+ dest='patched',
+ metavar='NAME',
+ help='''use NAME as patched 'master' branch name''')
+ p.add_option ('--dir-branch',
+ default=[],
+ dest='dir_branch',
+ metavar='DIR',
+ help='aggregate patches in directory DIR into one branch')
+ p.add_option ('--fuzz',
+ default='40', # FIXME: 40 = magic sweet spot for dev300-m21
+ dest='fuzz',
+ metavar='INT',
+ help='use FUZZ as fuzz factor for patch overlap')
+ p.add_option ('--force', action='store_true', dest='force', default=False)
+ p.add_option ('--split', action='store_true', dest='split', default=False)
+ p.add_option ('--topgit', action='store_true', dest='topgit', default=False)
+ p.add_option ('-v', '--verbose', action='count', dest='verbose', default=1)
+ p.add_option ('-q', '--quiet', action='count', dest='quiet', default=0)
+ return p
+
+def parse_options ():
+ p = get_cli_parser ()
+ (options, arguments) = p.parse_args ()
+
+ options.command = ''
+ options.arguments = []
+ if arguments:
+ options.command = re.sub ('-', '_', arguments.pop (0))
+ options.arguments = arguments
+
+ if options.command in Command.__dict__:
+ return options
+ if options.command:
+ sys.stderr.write ('no such command: ' + options.command)
+ sys.stderr.write ('\n\n')
+ p.print_help ()
+ sys.exit (2)
+
+def set_option_defaults (options):
+ options.flat_apply_dir = '.git/apply-dir'
+ options.verbose -= options.quiet
+ options.apply_dir = (options.apply_dir
+ .replace ('ooo300', 'dev300')
+ .replace ('ooo310', 'dev300')
+ .replace ('ooo320', 'dev300')
+ )
+ if not options.distros:
+ options.distros = ['SUSE']
+ if not options.dir_branch:
+ options.dir_branch = filter (lambda x: x not in ['.', '..', '.svn', '64bit', 'dev300', 'hotfixes'], list_dirs (options.apply_dir + '/..'))
+ too_dispersed = ['cairo', 'vba']
+ options.dir_branch = filter (lambda x: x not in too_dispersed, options.dir_branch)
+ return options
+
+options = None
+def main ():
+ global options
+ options = set_option_defaults (parse_options ())
+ apply_file = options.apply_dir + '/apply'
+ apply = Apply (apply_file, options.workspace, options.milestone)
+ Command.__dict__[options.command] (Command (apply, options))
+
+if __name__ == '__main__':
+ main ()
diff --git a/bin/gob.in b/bin/gob.in
deleted file mode 100755
index 627c9c6..0000000
--- a/bin/gob.in
+++ /dev/null
@@ -1,1070 +0,0 @@
-#!@PYTHON@
-
-# gob.py - ooo-build to GIT conversion: dump gob branch description files
-# and create branched git
-#
-# Usage: python bin/gob --help
-
-import optparse
-import operator
-import os
-import re
-import sys
-import shutil
-
-class SystemFailed (Exception):
- pass
-
-def log (s, threshold=1):
- if options.verbose > threshold:
- print >> sys.stderr, s
-
-def info (s):
- log (s, threshold=0)
-
-def exception_string (exception=Exception ('no message')):
- import traceback
- return traceback.format_exc (None)
-
-def filter_out (predicate, lst):
- return filter (lambda x: not predicate (x), lst)
-
-def makedirs (dir):
- log ('mkdir %(dir)s' % locals ())
- os.makedirs (dir)
-
-def symlink (src, dest):
- log ('ln -s %(src)s %(dest)s' % locals ())
- os.symlink (src, dest)
-
-def rename (src, dest):
- log ('mv %(src)s %(dest)s' % locals ())
- os.rename (src, dest)
-
-def rmdir (dir):
- log ('rmdir %(dir)s' % locals ())
- os.rmdir (dir)
-
-def system (command, raise_on_error=True):
- if options.verbose > 1:
- log ('executing: %(command)s' % locals ())
- if options.verbose < 3:
- command = '(%(command)s) > gob.log 2>&1' % locals ()
- status = os.system (command)
- if status and raise_on_error:
- info (command)
- info (file ('gob.log').read ())
- raise SystemFailed ('Command failed: %(command)s' % locals ())
- return status
-
-def read_pipe (command, raise_on_error=True):
- log ('executing: %(command)s' % locals ())
- if options.verbose < 3:
- command = '(%(command)s) 2> gob.log' % locals ()
- pipe = os.popen (command)
- output = pipe.read ()
- log ('pipe-output:\n%(output)s)s' % locals (), threshold=2)
- if pipe.close () and raise_on_error:
- info (command)
- info (file ('gob.log').read ())
- raise SystemFailed ('Pipe failed: %(command)s' % locals ())
- return output
-
-def list_dirs (dir, allow_link=True):
- return filter (lambda x: (os.path.isdir (os.path.join (dir, x))
- and (allow_link
- or not os.path.islink (os.path.join (dir, x)))),
- os.listdir (dir))
-
-def find_file (root, path, name):
- for dir in path:
- file_name = os.path.abspath (os.path.join (root, dir, name))
- if os.path.isfile (file_name):
- return file_name
- return None
-
-def _apply_patch (dir, patch):
- system ('patch -l -p0 -d %(dir)s < %(patch)s' % locals ())
-
-def apply_patch (dir, patch):
- if not options.split:
- return _apply_patch (dir, patch)
- apply_dir = os.path.join (dir, options.flat_apply_dir)
- _apply_patch (apply_dir, patch)
- for module in list_dirs (apply_dir, allow_link=False):
- rename (os.path.join (apply_dir, module), os.path.join (dir, module))
-
-def get_srcpack2_dict ():
- def modules_line (x):
- e = x.split ("=")
- return e[0], e[1].split (',')
- return dict (map (modules_line, file (src_dir + 'bin/modules2.txt').readlines ()))
-
-def for_each (func, lst):
- for i in lst:
- func (i)
-
-def move (src):
- src2 = get_srcpack2_dict ()
- def move_pack (pack):
- pack_dir = os.path.join (src, pack)
- def move_module (module):
- module_dir = src + '/' + module
- pack_module_dir = pack_dir + '-/' + module
- if os.path.exists (module_dir):
- rename (module_dir, pack_module_dir)
- makedirs (pack_dir + '-')
- for_each (move_module, src2[pack])
- rename (pack_dir + '-', pack_dir)
- for_each (move_pack, src2.keys ())
-
-def move_back (src):
- src2 = get_srcpack2_dict ()
- def move_pack (pack):
- pack_dir = os.path.join (src, pack)
- def move_module (module):
- print 'renaming:', module
- module_dir = src + '/' + module
- pack_module_dir = pack_dir + '-/' + module
- if os.path.exists (pack_module_dir):
- rename (pack_module_dir, module_dir)
- else:
- print 'no such dir:', pack_module_dir
- rename (pack_dir, pack_dir + '-')
- for_each (move_module, src2[pack])
- rmdir (pack_dir + '-')
- for_each (move_pack, src2.keys ())
-
-def setup_flat_apply_dir (src):
- src2 = get_srcpack2_dict ()
- apply_dir = os.path.join (src, options.flat_apply_dir)
- shutil.rmtree (apply_dir, ignore_errors=True)
- makedirs (apply_dir)
- missing = ['mdbtools', 'libwpg', 'libwps', 'xalan']
- for pack in src2.keys ():
- for module in src2[pack]:
- symlink (os.path.join ('..', '..', pack, module), os.path.join (apply_dir, module))
- for pack in missing:
- symlink (os.path.join ('..', '..', pack), os.path.join (apply_dir, pack))
-
-def patch_get_branch (patch):
- patch_file = patch.file_name
- if not patch_file:
- return None
-
- if 'vba' in options.dir_branch and int (options.milestone) > 19:
- m = re.search ('(cws-scsheetprotection02|sc-autofilter-empty-nonempty|sc-copy-source-border|sc-datapilot|sc-move-from-origin|sc-paste-on-enter|sc-save-password-minlength|scroll-accel|xl-import-formradiobutton)', patch_file)
- if m:
- return 'vba'
-
- # Prevent from going into ooxml
- m = re.search ('(writerfilter-qnametostr-NOOPTFILES)', patch_file)
- if m:
- return m.group (1)
-
- dir = os.path.basename (os.path.dirname (patch_file))
- base = os.path.splitext (os.path.basename (patch_file))[0]
-
- module_re = None
- if not module_re:
- modules = list_dirs (options.build_dir)
- if options.split:
- modules = list_dirs (os.path.join (options.build_dir, options.flat_apply_dir))
- module_re = '|'.join (modules)
-
- # Patches with a simple digit suffix are aggregated into one branch
- if (not re.search ('%(module_re)s$|\d\d+$' % locals (), base)
- and re.search ('\d$', base)):
- base = re.sub ('-*\d$', '', base)
-
- # Patches in a separated may be aggregated into one branch
- if dir in options.dir_branch:
- return dir
-
- # Pathes with a branch_prefix are aggregated into one branch
- branch_prefix = [
- 'cjk-character-units',
- 'cws-layoutdialogs',
- 'cws-scsheetprotection02',
- 'emf+',
- 'fpicker-kde',
- 'jvmfwk-gij',
- 'lockfile',
- 'mono',
- 'sal-strintern-speed',
- 'sc-dataform',
- 'sc-datapilot',
- 'speed-configmgr',
- 'svg-import',
- 'system-lpsolve',
- 'tools-urlobj-smb-scheme',
- 'transogl',
- 'unittesting',
- 'unxsplash',
- 'vba',
- 'wpgimporter',
- 'writerfiltery'
- ]
-
- branch_prefix_re = '^(' + '|'.join (branch_prefix).replace ('+', '\+') + ')'
- m = re.search (branch_prefix_re, base)
- if m:
- def assert_dir_group (m, s):
- return s in options.dir_branch or m.group (1) != s
- if (assert_dir_group (m, 'vba')
- and assert_dir_group (m, 'emf+')
- and assert_dir_group (m, 'unittesting')):
- return m.group (1)
-
- # Some patches are declared in the middle of a branch [another
- # series of patches that form a branch] which depends on that
- # patch, but have derogatory naming. These patches must be
- # categorised explicitly. The ASSIMILATE warning helps to detect
- # these.
- if 'emf+' in options.dir_branch and re.search ('^(cairocanvas-alpha-pixmap-rewrite|vcl-grey-alpha-unix-sal-bitmap)', base):
- return 'emf+'
-
- if 'ooxml' in options.dir_branch and re.search ('^(win32-installer-register-moox-types)', base):
- return 'ooxml'
-
- if 'vba' in options.dir_branch and re.search ('^(default-autotext-and-form-name|sc-toggle-merge-center)', base):
- return 'vba'
-
- if re.search ('^(fix-linkoo|linkoo-)', base):
- return 'linkoo'
-
- if re.search ('^(fpicker-common-scp2)', base):
- return 'fpicker-kde'
-
- # Remove workspace and milestone suffixes
- workspace = options.workspace
- milestone = options.milestone
- base = re.sub ('-%(workspace)s' % locals (), '', base)
- base = re.sub ('-m%(milestone)s' % locals (), '', base)
-
- # Patches with a -localize suffix are aggregated into one branch
- base = re.sub ('-localize$' % locals (), '', base)
-
- # Patches with a module suffix are aggregated into one branch
- base = re.sub ('-(%(module_re)s)$' % locals (), '', base)
-
- # git does not like dots in branch names
- base = base.replace('.','-')
-
- return base
-
-# Hard handy work for m19 gets quickly bit rotten
-# Use patch dependency calculation instead
-manual_m19_branch_dependencies = {
- 'buildfix-layoutdialogs': ['cws-layoutdialogs'],
- 'cairocanvas-fix-image-cache': ['cairo'],
- 'cws-scsheetprotection02': ['sc-datapilot', 'sc-paste-on-enter'],
- 'emf+': ['link-as-needed'],
- 'forms-radio-button-group-names': ['form-control-visibility'],
- 'layout-plugin': ['cws-layoutdialogs'],
- 'layout-tab': ['layout-plugin'],
- 'linkwarn-svtools-miscopts-bits': ['novell-win32-odma'],
- 'ooo59127.vcl.honourcairofont': ['ooo64508.vcl.honourfontconfighinting'],
- 'oosplash-etc-openoffice-sofficerc': ['unxsplash'],
- 'ooxml': ['lwp-filter-component'],
- 'sc-copy-on-merged-cells': ['sc-dataform'],
- 'sc-dataform': ['sc-hrc-ooo-build-resources'],
- 'sc-datapilot': ['sc-dataform'],
- 'sc-dp-gridlayout': ['sc-datapilot'],
- 'sc-export-shape-hlink-bindings': ['sc-export-shape-macro-bindings'],
- 'sc-simple-sort-include-format-header': ['sc-natural-sort'],
- 'sc-toggle-merge-center': ['vba'],
- 'sfx2-pre-and-postprocess-crash-fix': ['sfx2-pre-and-postprocess-during-save-load'],
- 'sfx2-pre-and-postprocess-during-save-load': ['sfx2-remove-check-update-on-fileload'],
- 'speed-bdirect': ['speed-symbolic-functions'],
- 'speed-store-lck': ['store-core'],
- 'static-libs-use-_pic': ['system-lpsolve'],
- 'ui-desktop-integration': ['linkwarn-svtools-miscopts-bits'],
- 'unittesting': ['tools-qa-urlobj-unittest', 'gnome-vfs-late-init'],
- 'vba': ['cws-npower10', 'cws-pflin10', 'cws-npower11'],
- 'vcl-linking-randr': ['autocorrect-accidental-caps-lock', 'internal-mesa-headers'],
- 'wpgimporter': ['wpsimport'],
-}
-
-def range_union (a, b, fuzz=0):
- u = (max (a[0], b[0]) - fuzz, min (a[1], b[1]) + fuzz, a[2], b[2])
- if u[0] > u[1]:
- return None
- return u
-
-class File:
- def __init__ (self, s):
- self.string = s
- self.ranges = None
- self.name = None
- if self.string.find ('\n+++ ') >= 0:
- self.name = re.search ('\n[+]{3}\s+([.]/)?([^\s]+)', self.string).group (2)
- def __repr__ (self):
- return '<File: %(name)s>' % self.__dict__
- def get_ranges (self):
- if not self.ranges:
- self.numbers = re.findall ('\n(@@ -(\d+),(\d+) [+](\d+),(\d+) @@(.|\n[^@])*)', self.string)
- self.ranges = map (lambda x: (min (int (x[1]), int (x[3])), max (int (x[1]) + int (x[2]), int (x[3]) + int (x[4])), x[0][:160]), self.numbers)
- return self.ranges
-
-def patch_depend (p, q):
- files = []
- for file_name in p.files.keys ():
- if file_name in q.files.keys ():
- for a in p.files[file_name].get_ranges ():
- for b in q.files[file_name].get_ranges ():
- union = range_union (a, b, int (options.fuzz))
- if union:
- return union
- return False
-
-def patch_get_dependencies (patches, patch):
- dependencies = ['pristine']
- for p in patches:
- if p == patch:
- break
- if patch_depend (patch, p):
- dependencies += [p.name]
- return dependencies
-
-def branch_get_dependencies (branches, patches, branch):
- patch_dependencies = {}
- patch_overlaps = []
- first_patch = None
- for patch in patches:
- if patch in branches[branch]:
- first_patch = patch
- break
- last_patch = None
- for patch in reversed (patches):
- if patch in branches[branch]:
- last_patch = patch
- break
- for patch in branches[branch]:
- assimilate = False
- for p in patches:
- if p == last_patch:
- name = p.name
- break
- if p == first_patch:
- name = p.name
- # We cannot have a branch pre-depend on a patch/branch
- # that does not exist yet. FIXME: if it is really
- # needed, it should be auto-assimilated by the branch.
- # This is now done manually in patch_get_branch ().
- assimilate = True
- o = patch_depend (patch, p)
- if assimilate and o and p not in branches[branch]:
- name = p.name
- ab = patch_get_branch (p)
- print 'ASSIMILATE[%(branch)s]: %(name)s [%(ab)s]' % locals ()
- continue
- if o:
- patch_dependencies[p] = p
- patch_overlaps += [o]
- branch_dependencies = {}
- for patch in patch_dependencies.values ():
- b = patch_get_branch (patch)
- if b != branch:
- branch_dependencies[b] = b
- if not branch_dependencies:
- return ['pristine']
- return branch_dependencies.values ()
-
-# No overrides are necessary when using fuzz >= 40
-branch_override_dependencies = {
- }
-
-def branch_get_dependencies_with_override (branches, patches, branch):
- return branch_override_dependencies.get (branch, branch_get_dependencies (branches, patches, branch))
-
-GitFailed = SystemFailed
-
-gitignores = '''
-*-
-*-HEAD
-*-git
-*-patched
-*-pristine
-*.bak
-*.cxx-*
-*.deps
-*.git
-*.hxx-*
-*.log
-*.orig
-*.patched
-*.pristine
-*.pyc
-*.rej
-*~
-.\#*
-/Linux*Env.Set*
-/bootstrap
-/makefile.mk
-/solver
-CVS
-TAGS
-\#*
-xxx-have-in-patches-now:localize.sdf
-unxlng*.pro
-autom4te.cache/
-config.log
-config.parms
-config.status
-configure
-set_soenv
-tmon.out
-visibility.cxx
-visibility.s
-warn
-default_images/introabout/intro-save.bmp
-dmake/Makefile
-dmake/config.h
-dmake/config.log
-dmake/config.status
-dmake/dmake
-dmake/*.o
-dmake/dmakeroot.h
-dmake/stamp-h1
-dmake/startup/Makefile
-dmake/startup/config.mk
-dmake/startup/unix/Makefile
-dmake/startup/unix/cygwin/Makefile
-dmake/startup/unix/linux/Makefile
-dmake/startup/unix/macosx/Makefile
-dmake/startup/unix/solaris/Makefile
-dmake/startup/unix/sysvr4/Makefile
-dmake/startup/winnt/Makefile
-dmake/startup/winnt/mingw/Makefile
-dmake/startup/winnt/msvc6/Makefile
-dmake/tests/Makefile
-dmake/unix/.dirstamp
-instsetoo_native/res/banner_nld.bmp
-instsetoo_native/res/banner_ooop.bmp
-instsetoo_native/res/nologoinstall_nld.bmp
-instsetoo_native/res/nologoinstall_ooop.bmp
-instsetoo_native/util/OpenOffice
-sd/xml/transitions-ogl.xml
-setup_native/source/win32/nsis/ooobanner_nld.bmp
-setup_native/source/win32/nsis/ooobanner_ooop.bmp
-setup_native/source/win32/nsis/ooobitmap_nld.bmp
-setup_native/source/win32/nsis/ooobitmap_ooop.bmp
-setup_native/source/win32/nsis/ooosetup_nld.ico
-solenv/unxlng*/
-svx/res
-'''
-keep = '''
-default_images/introabout/intro-save.bmp
-default_images/introabout/intro.bmp
-default_images/svx/res/openabout_ark.png
-default_images/svx/res/openabout_translateorgza.png
-default_images/sw/res/go-oo-team.png
-'''
-
-def create_gitignores (dir):
- for i in filter_out (operator.not_, gitignores.split ('\n')):
- if options.split:
- i = i.replace ('/bootstrap', '/bootstrap/bootstrap')
- if i[0] == '/':
- file (dir + '/.gitignore', 'a').write (i + '\n')
- else:
- slash = ''
- if i[-1] == '/':
- i = i[:-1]
- slash = '/'
- file (dir + '/' + os.path.dirname (i) + '/.gitignore', 'a').write (os.path.basename (i) + slash + '\n')
-
-class Setup:
- string = None
- vars = {}
- def __init__ (self, file_name='config.log'):
- if not self.string and os.path.exists (file_name):
- self.string = file (file_name).read ()
- def get (self, key, default=None):
- return self.vars.get (key, self.read_ (key, default))
- def read_ (self, key, default):
- m = re.search ('''%(key)s=['"*]([^*"']*)''' % locals (), self.string)
- if m:
- self.vars[key] = m.group (1)
- else:
- self.vars[key] = default
- return self.vars[key]
-
-def get_svn_revision ():
- return re.search ('\nRevision: ([0-9]+)', read_pipe ('svn info')).group (1)
-
-def get_git_committish ():
- return re.search ('([^ ]+)', read_pipe ('git log --pretty=oneline -1')).group (1)
-
-class Git:
- def __init__ (self, dir, patched, clean=False):
- self.dir = dir
- self.patched = patched
- self.scratch = 'work/scratch'
- self.workspace = options.workspace
- self.milestone = options.milestone
- self.pristine = 'upstream/%(workspace)s-m%(milestone)s' % self.__dict__
- self.commits = {}
- self.log = {}
- if not os.path.exists (self.dir):
- drink = Setup ().get ('DRINK', 'tea')
- info ('Unpacking source tree - [ go and have some %(drink)s ] ...' % locals ())
- system ('cd bin && ./unpack')
- create_gitignores (dir)
- if options.split:
- move (self.dir)
- setup_flat_apply_dir (self.dir)
- self.system ('touch unpack')
- if not os.path.isdir (dir + '/.git/refs'):
- drink = Setup ().get ('DRINK')
- info ('Creating GIT archive - [ go and have some %(drink)s ] ...' % locals ())
- self.system ('git init')
- #svn_revision = get_svn_revision ()
- #self.commit ('Initial svn:r%(svn_revision)s unpatched.' % locals ())
- git_committish = get_git_committish ()
- self.commit ('Initial ooo-build: %(git_committish)s unpatched.' % locals ())
- self.system ('git branch %(pristine)s' % self.__dict__)
- self.system ('git tag gob-%(workspace)s-%(milestone)s %(pristine)s' % self.__dict__)
- self.system ('git branch pristine')
- self.system ('git gc')
- if clean:
- if self.is_modified ():
- self.system ('git reset --hard HEAD')
- self.system ('git clean -df')
- if self.has_branch (self.patched):
- self.checkout (self.patched)
- else:
- self.system ('git checkout -b %(patched)s pristine' % self.__dict__)
- if self.has_branch (self.scratch):
- self.system ('git branch -D %(scratch)s' % self.__dict__)
- def pipe (self, command, raise_on_error=True):
- dir = self.dir
- return read_pipe ('cd %(dir)s && %(command)s' % locals (), raise_on_error)
- def system (self, command, raise_on_error=True):
- dir = self.dir
- return system ('cd %(dir)s && %(command)s' % locals (), raise_on_error)
- def get_branches (self):
- return filter_out (operator.not_,
- self.pipe ('git branch')
- .replace ('*', '')
- .replace (' ', '').split ('\n'))
- def get_log (self, branch=''):
- commit = self.get_current_commit (branch)
- self.log[commit] = self.log.get (commit, self.pipe ('git log --pretty=oneline %(branch)s --' % locals ()))
- return self.log[commit]
- def get_current_commit (self, branch=''):
- if not branch:
- branch = 'HEAD'
- return self.pipe ('git rev-parse %(branch)s' % locals ())[:-1]
- def get_commit (self, patch):
- if not self.commits:
- log = self.get_log (self.patched)
- def grok_log_line (s):
- m = re.match ('([^ ]+) Apply.*/([^/]+[.](diff|patch))', s)
- if not m:
- info ('Skipping line:%(s)s:' % locals ())
- return None, None
- return m.group (2), m.group (1)
- self.commits = dict (map (grok_log_line, log.split ('\n')[:-2]))
- return self.commits.get (patch, None)
- def commit (self, message):
- self.system ('git add .')
- self.system ('git add -u .')
- self.system ('''git commit -m '%(message)s' ''' % locals ())
- def is_modified (self):
- return re.sub ('# On branch.*\nnothing to commit \(working directory clean\)\n', '',
- self.pipe ('git status', raise_on_error=False))
- def assert_clean (self):
- dir = self.dir
- pending = self.is_modified ()
- if pending:
- raise GitFailed ('working directory unclean: %(dir)s\n%(pending)s' % locals ())
- def checkout (self, branch):
- if not self.is_on_branch (branch):
- self.system ('git checkout %(branch)s' % locals ())
- def get_current_branch (self):
- return self.pipe ('git symbolic-ref HEAD', raise_on_error=False)[len ('refs/heads/'):-1]
- def is_on_branch (self, branch):
- return branch == self.get_current_branch ()
- def has_branch (self, branch):
- return branch in self.get_branches ()
- def apply_patch (self, branches, patches, patch):
- branch = patch_get_branch (patch)
- info ('Applying patch[%(branch)s]: ' % locals () + patch.name)
- patched = self.get_current_branch ()
- apply_patch (self.dir, patch.file_name)
- base = os.path.basename (patch.file_name)
- self.commit ('Apply %(base)s.' % locals ())
- if options.milestone == '19':
- dependencies = manual_m19_branch_dependencies.get (branch, ['pristine'])
- else:
- dependencies = branch_get_dependencies_with_override (branches, patches, branch)
- if not self.has_branch (branch):
- if not options.topgit:
- base_depend = dependencies[0]
- self.system ('git checkout -b %(branch)s %(base_depend)s' % locals ())
- for dependency in dependencies[1:]:
- self.system ('git rebase %(dependency)s' % locals ())
- else:
- depend_str = ' '.join (dependencies)
- self.system ('tg create %(branch)s %(depend_str)s' % locals ())
- self.system ('git commit -am "topgit branch info %(branch)s"' % locals ())
- else:
- self.checkout (branch)
- log = self.get_log (patched)
- commit = log[:log.index (' ')]
- self.system ('git cherry-pick -x %(commit)s' % locals ())
- def before_ (self):
- self.assert_clean ()
- self.system ('git checkout -b %(scratch)s %(patched)s' % self.__dict__)
- def after_ (self):
- self.system ('git push . %(scratch)s:%(patched)s' % self.__dict__)
- self.checkout (self.patched)
- self.system ('git branch -D %(scratch)s' % self.__dict__)
- def pick_patch (self, patch, commit):
- branch = patch_get_branch (patch)
- info ('Picking patch[%(branch)s]: ' % locals () + patch.name)
- self.system ('git cherry-pick -x %(commit)s' % locals ())
- def add_patch (self, branches, patches, patch):
- if patch.name in self.get_log ():
- info ('patch already applied, skipping: ' + patch.name)
- return
- if file (patch.file_name).read ().find ('\n+++ ') == -1:
- info ('patch is empty, skipping: ' + patch.name)
- return
- commit = None
- branch = patch_get_branch (patch)
- if self.has_branch (branch):
- name = patch.name.replace ('+', '\+')
- m = re.search ('(^|\n)([^\s]+)\s+.*(\s|/)%(name)s' % locals (), self.get_log (branch))
- if m:
- commit = m.group (2)
- self.before_ ()
- if commit:
- self.pick_patch (patch, commit)
- else:
- self.apply_patch (branches, patches, patch)
- self.after_ ()
- def dump_gob (self, branches, patches, branch):
- gob_dir = self.dir + '/.git/refs/gob'
- if not os.path.exists (gob_dir):
- makedirs (gob_dir)
- branch_patches = branches.get (branch, [])
- if not branch_patches:
- return
- owner = ''
- for patch in branch_patches:
- owner = patch.owner
- if owner:
- break
- issues = []
- for patch in branch_patches:
- issues += patch.issues
- issue_string = ', '.join (issues)
- dependencies = filter (lambda x: x != 'pristine', branch_get_dependencies (branches, patches, branch))
- dependencies_string = ', '.join (dependencies)
- commit = self.get_current_commit ()
- gob_file_name = os.path.join (gob_dir, branch)
- info ('Writing: ' + gob_file_name)
- file (gob_file_name, 'w').write ('''%(commit)s
-state: stable
-issue: %(issue_string)s
-owner: %(owner)s
-depend: %(dependencies_string)s
-''' % locals ())
-
-class Patch:
- def __init__ (self, file_name):
- self.file_name = file_name
- if self.file_name:
- self.set_files ()
- self.file_name = None
- def set_files (self):
- self.files = dict (map (lambda x: (x.name, x), map (File, ('\n' + file (self.file_name).read ()).split ('\n---')[1:])))
- def __repr__ (self):
- return '<Patch: ' + str (map (str, self.files.values ())) + ' >'
-
-class Apply_patch (Patch):
- def __init__ (self, s, section, owner, issue):
- Patch.__init__ (self, None)
- self.string = s
- self.section = section
- self.owner = owner
- m = re.search (', (\w\w+)', self.string)
- if m:
- self.owner = m.group (1)
- m = re.match ('^\s*(([^#\s].*).(diff|patch))(.*)', self.string)
- self.name = m.group (1)
- self.base = m.group (2)
- self.issues = map (lambda x: x[0], re.findall ('((i|n)#[0-9]+)', self.string))
- if issue:
- self.issues.append (issue)
- def __repr__ (self):
- return '<Patch: %(file_name)s [%(section)s] %(owner)s %(issues)s>' % self.__dict__
- def set_file_name (self, dir, path):
- self.file_name = find_file (dir, path, self.name)
- self.set_files ()
- return self
-
-class Section:
- def __init__ (self, s):
- self.string = s
- m = re.match ('[[\s]*(.*[^\s])\s*\]', self.string)
- self.tag = m.group (1).replace (' ', '')
- self.name = re.sub ('[^\w].*', '', self.tag)
- m = re.search ('\n(SectionOwner)\s*=>\s*(.*[^\s])', self.string)
- self.owner = ''
- if m:
- self.owner = m.group (2)
- m = re.search ('\n(SectionIssue)\s*=>\s*(.*[^\s])', self.string)
- self.issue = ''
- if m:
- self.issue = m.group (2)
- def __repr__ (self):
- return '<Section: %(tag)s %(owner)s %(issue)s>' % self.__dict__
- def get_patches (self):
- def create_patch (s):
- return Apply_patch (s[0], self.tag, self.owner, self.issue)
- return map (create_patch, re.findall ('\n\s*([^#\s].*.(diff|patch).*)', self.string))
-
-class Apply:
- def __init__ (self, apply_file, workspace, milestone):
- self.workspace = workspace
- self.milestone = milestone
- self.string = file (apply_file).read ()
- first_section = self.string.index ('\n[')
- self.distros_string = self.string[:first_section]
- self.sections_string = self.string[first_section:]
- self.path = re.search ('\nPATCHPATH=(.*)', self.string).group (1).split (':')
- self.distro = {}
- self.master = {}
- self.distros_string = re.sub ('\s*\\\s*\n\s*', '', self.distros_string)
- for distro in re.findall ('\n\s*([^#=\s:]+)\s*:\s*(.*)', self.distros_string):
- lst = distro[1].replace (' ', '').split (',')
- expanded = []
- for i in lst:
- if i in self.master.keys ():
- del self.master[i]
- expanded += self.distro.get (i, [i])
- self.master[distro[0]] = self.distro[distro[0]] = expanded
- # convenience: add sections as distro
- #self.distro.update (dict (map (lambda x: (x.name, x.name), self.get_sections ())))
- def get_section_strings (self):
- return map (lambda x: '[' + x, self.sections_string.split ('\n[')[1:])
- def get_sections (self):
- return map (Section, self.get_section_strings ())
- def get_distro (self, distro_name):
- def section_in_distro (section):
- if distro_name not in self.distro.keys ():
- return distro_name == section.name
- m = re.search ('(\w+).*(<=|<|==|!=|>=|>)%(workspace)s-m([0-9]+)'
- % self.__dict__, section.tag)
- if m:
- name = m.group (1)
- if not name in self.distro[distro_name]:
- return False
- left_milestone = self.milestone
- operator = m.group (2)
- right_milestone = int (m.group (3))
- return eval ('%(left_milestone)s %(operator)s %(right_milestone)s' % locals ())
- else:
- return section.tag in self.distro[distro_name]
- return filter (section_in_distro, self.get_sections ())
-
-class Command:
- def __init__ (self, apply, options):
- self.options = options
- self.apply = apply
- self.patches_ = []
- self.branches_ = {}
- def patches (self):
- '''list patches'''
- print '\n'.join (map (str, self.get_patches ()))
- def sections (self):
- '''list sections'''
- print '\n'.join (map (str, self.get_sections ()))
- def distros (self):
- '''list distros'''
- print '\n'.join (map (str, self.apply.distro.keys ()))
- def masters (self):
- '''list masters'''
- print '\n'.join (map (str, self.apply.master.keys ()))
- def branches (self):
- '''list branches'''
- print '\n'.join (map (str, self.get_branches ().keys ()))
- def get_branches (self):
- if not self.branches_:
- for patch in self.get_patches ():
- branch = patch_get_branch (patch)
- self.branches_[branch] = self.branches_.get (branch, []) + [patch]
- return self.branches_
- def dump_gobs (self):
- '''dump gob files'''
- branches = self.get_branches ()
- patches = self.get_patches ()
- git = Git (self.options.build_dir, self.options.patched)
- for branch in git.get_branches ():
- git.dump_gob (branches, patches, branch)
- def checkout (self):
- '''checkout patched ('master') branch'''
- git = Git (self.options.build_dir, self.options.patched)
- def git_export (self):
- '''export to GIT with branches'''
- git = Git (self.options.build_dir, self.options.patched, clean=True)
- patches = self.get_patches ()
- branches = self.get_branches ()
- for patch in self.get_patches ():
- git.add_patch (branches, patches, patch)
- git.system ('git gc')
- def get_patches_for_distro (self, distro):
- patches = reduce (operator.add, map (lambda section: section.get_patches (), self.get_sections_for_distro (distro)))
- for patch in patches:
- patch.set_file_name (self.options.apply_dir, self.apply.path)
- return patches
- def get_patches (self):
- if not self.patches_:
- self.patches_ = reduce (operator.add, map (self.get_patches_for_distro, self.options.distros))
- return self.patches_
- def get_sections_for_distro (self, distro):
- return self.apply.get_distro (distro)
- def get_sections (self):
- return reduce (operator.add, map (self.get_sections_for_distro, self.options.distros))
- def prepare (self):
- '''prepare ooo-build dir for use with GIT'''
- git = Git (self.options.build_dir, self.options.patched)
- def postpare (self):
- '''update ooo-build dir GIT after patching'''
- git = Git (self.options.build_dir, self.options.patched)
- #svn_revision = get_svn_revision ()
- #git.commit ('Update to svn:r%(svn_revision)s patched.' % locals ())
- git_committish = get_git_committish ()
- git.commit ('Update to ooo-build: %(git_committish)s patched.' % locals ())
- git.system ('git rebase patched')
- def dependencies (self):
- '''list branch dependencies'''
- patches = self.get_patches ()
- branches = self.get_branches ()
- independent = 0
- for branch in branches:
- dependencies = sorted (branch_get_dependencies (branches, patches, branch))
- if dependencies == ['pristine']:
- independent += 1
- print 'BRANCH:', branch, '->', dependencies
- print 'INDEPENDENT:', independent
- def patch_dependencies (self):
- '''list patch dependencies'''
- branches = self.get_branches ()
- patches = self.get_patches ()
- for patch in patches:
- branch = patch_get_branch (patch)
- name = patch.name
- print 'PATCH[%(branch)s]: %(name)s -> ' % locals (), patch_get_dependencies (patches, patch)
- def bump (self):
- '''bump BRANCH TAG-NAME - bump current branch (BRANCH=new upstream)'''
- if len (self.options.arguments) != 2:
- print 'Usage: gob bump BRANCH TAG-NAME'
- print 'BRANCH: new upstream'
- print 'Example:'
- print ' gob bump upstream/dev300-m21 my-21-update'
- sys.exit (2)
- branch = self.options.arguments[0]
- tag = self.options.arguments[1]
- git_dir = self.options.build_dir
- system ('cd %(git_dir)s && gob-bump %(branch)s %(tag)s' % locals ())
- def update (self):
- '''update BRANCH - update current branch (BRANCH='master')'''
- if len (self.options.arguments) != 1:
- print 'Usage: gob update BRANCH'
- print '''BRANCH: the 'master' branch'''
- print 'Example: '
- print ' gob update distro/SUSE'
- sys.exit (2)
- branch = self.options.arguments[0]
- git_dir = self.options.build_dir
- system ('cdi %(git_dir)s && gob-update %(branch)s' % locals ())
- def reset (self):
- '''reset - set GIT tree to pristine and remove all branches'''
- git = Git (self.options.build_dir, self.options.patched)
- git.system ('git checkout -f %(patched)s' % git.__dict__)
- git.system ('git reset --hard pristine')
- git.system ('git clean -df')
- git.system ('rm -rf .git/refs/top-bases')
- cmd = 'xargs git branch -D'
- if options.split:
- git.system ('''git branch | grep -Ev '/|master|patched|pristine|upstream|%(patched)s' | xargs tg delete -f ''' % git.__dict__)
- git.system ('''git branch | grep -Ev '/|master|patched|pristine|upstream|%(patched)s' | xargs git branch -D''' % git.__dict__)
- def patch_depend (self):
- '''patch-depend PATCH-1 PATCH-2 - show overlap between patches'''
- if len (self.options.arguments) != 2:
- print 'Usage: patch-depend PATCH-1 PATCH-2'
- sys.exit (2)
- union = patch_depend (Patch (self.options.arguments[0]), Patch (self.options.arguments[1]))
- if union:
- print union[0], '--', union[1]
- print union[2]
- print '<<<<<<<<<<<<<<<<<<<<<<<<<=========================>>>>>>>>>>>>>>>>>>>>>>>>>'
- print union[3]
- sys.exit (1)
- def statistics (self):
- ### not advertised
- ### show some statistics on dependensies
- patches = self.get_patches ()
- branches = self.get_branches ()
- full_match = 0
- match = 0
- fail = 0
- extra = 0
- independent = 0
- for branch in branches:
- manual_dependencies = sorted (manual_m19_branch_dependencies.get (branch, ['pristine']))
- auto_dependencies = sorted (branch_get_dependencies (branches, patches, branch))
- missing = False
- for m in manual_dependencies:
- if m != 'pristine' and not m in auto_dependencies:
- missing = True
- break
- if missing:
- fail += 1
- print
- print 'BRANCH:', branch
- print 'MANUAL:', manual_dependencies
- print 'AUTO:', auto_dependencies
- #dependencies 'OVERLAPS:', overlaps
- if auto_dependencies == ['pristine']:
- independent += 1
- elif auto_dependencies == manual_dependencies:
- full_match += 1
- elif manual_dependencies == ['pristine']:
- extra += 1
- #print 'BRANCH:', branch
- #print 'EXTRA:', auto_dependencies
- elif not missing:
- match += 1
- print
- print 'FAIL:', fail
- print 'FULL_MATCH:', full_match
- print 'MATCH:', match
- print 'EXTRA:', extra
- print 'INDEPENDENT:', independent
- def move (self):
- move (options.build_dir)
- setup_flat_apply_dir (options.build_dir)
- def move_back (self):
- move_back (options.build_dir)
-
-def get_cli_parser ():
- p = optparse.OptionParser ()
-
- p.usage = '%prog [OPTION]... COMMAND\n\nCommands:\n'
- d = Command.__dict__
- commands = [(k, d[k].__doc__) for k in d.keys ()
- if d[k].__doc__ and type (d[k]) == type (lambda x: x)]
- commands.sort ()
-
- global src_dir
- src_dir = ''
- if not os.path.exists ('patches'):
- src_dir = '../'
- os.environ['PATH'] = src_dir + '/bin:' + os.environ['PATH']
-
- for (command, doc) in commands:
- p.usage += ' %s - %s\n' % (re.sub ('_', '-', command), doc)
-
- def get (option):
- return p.get_option ('--' + option.replace ('-', '_')).default
-
- setup_workspace, setup_milestone = Setup ().get ('CVSTAG', 'dev300-m19').split ('-m')
-
- p.add_option ('--workspace',
- dest='workspace',
- default=setup_workspace,
- metavar='STRING',
- help='set master workspace')
- p.add_option ('--milestone',
- dest='milestone',
- default=setup_milestone,
- metavar='STRING',
- help='set milestone')
- p.add_option ('--distro',
- action='append',
- dest='distros',
- default=[],
- metavar='DISTRO',
- help='add distribution')
- p.add_option ('--build-dir',
- default=src_dir + 'build/' + get ('workspace') + '-m' + get ('milestone'),
- dest='build_dir',
- metavar='DIR',
- help='build (/git) directory')
- p.add_option ('--apply-dir',
- default=src_dir + 'patches/' + get ('workspace'),
- dest='apply_dir',
- metavar='DIR',
- help='directory with APPLY file')
- p.add_option ('--patched',
- default='patched',
- dest='patched',
- metavar='NAME',
- help='''use NAME as patched 'master' branch name''')
- p.add_option ('--dir-branch',
- default=[],
- dest='dir_branch',
- metavar='DIR',
- help='aggregate patches in directory DIR into one branch')
- p.add_option ('--fuzz',
- default='40', # FIXME: 40 = magic sweet spot for dev300-m21
- dest='fuzz',
- metavar='INT',
- help='use FUZZ as fuzz factor for patch overlap')
- p.add_option ('--force', action='store_true', dest='force', default=False)
- p.add_option ('--split', action='store_true', dest='split', default=False)
- p.add_option ('--topgit', action='store_true', dest='topgit', default=False)
- p.add_option ('-v', '--verbose', action='count', dest='verbose', default=1)
- p.add_option ('-q', '--quiet', action='count', dest='quiet', default=0)
- return p
-
-def parse_options ():
- p = get_cli_parser ()
- (options, arguments) = p.parse_args ()
-
- options.command = ''
- options.arguments = []
- if arguments:
- options.command = re.sub ('-', '_', arguments.pop (0))
- options.arguments = arguments
-
- if options.command in Command.__dict__:
- return options
- if options.command:
- sys.stderr.write ('no such command: ' + options.command)
- sys.stderr.write ('\n\n')
- p.print_help ()
- sys.exit (2)
-
-def set_option_defaults (options):
- options.flat_apply_dir = '.git/apply-dir'
- options.verbose -= options.quiet
- options.apply_dir = (options.apply_dir
- .replace ('ooo300', 'dev300')
- .replace ('ooo310', 'dev300')
- .replace ('ooo320', 'dev300')
- )
- if not options.distros:
- options.distros = ['SUSE']
- if not options.dir_branch:
- options.dir_branch = filter (lambda x: x not in ['.', '..', '.svn', '64bit', 'dev300', 'hotfixes'], list_dirs (options.apply_dir + '/..'))
- too_dispersed = ['cairo', 'vba']
- options.dir_branch = filter (lambda x: x not in too_dispersed, options.dir_branch)
- return options
-
-options = None
-def main ():
- global options
- options = set_option_defaults (parse_options ())
- apply_file = options.apply_dir + '/apply'
- apply = Apply (apply_file, options.workspace, options.milestone)
- Command.__dict__[options.command] (Command (apply, options))
-
-if __name__ == '__main__':
- main ()
diff --git a/configure.in b/configure.in
index 90500e4..b1df923 100644
--- a/configure.in
+++ b/configure.in
@@ -1630,7 +1630,6 @@ AC_SUBST(OOO_ADDITIONAL_SECTIONS)
AC_CONFIG_FILES([bin/font-munge], [chmod +x bin/font-munge])
-AC_CONFIG_FILES([bin/gob], [chmod +x bin/gob])
AC_CONFIG_FILES([bin/help-font-munge], [chmod +x bin/help-font-munge])
AC_CONFIG_FILES([download], [chmod +x download])
AC_CONFIG_FILES([scratch/place], [chmod +x scratch/place])
More information about the ooo-build-commit
mailing list