diff -ru orig_portage/bin/dispatch-conf git_portage/bin/dispatch-conf --- orig_portage/bin/dispatch-conf 2008-11-15 07:09:35.000000000 +0100 +++ git_portage/bin/dispatch-conf 2009-02-28 15:27:34.000000000 +0100 @@ -32,6 +32,11 @@ DIFF_CONTENTS = "diff -Nu '%s' '%s'" DIFF_CVS_INTERP = "diff -Nu '%s' '%s' | grep '^[+-][^+-]' | grep -v '# .Header:.*'" DIFF_WSCOMMENTS = "diff -Nu '%s' '%s' | grep '^[+-][^+-]' | grep -v '^[-+]#' | grep -v '^[-+][:space:]*$'" +GIT_INIT_DB = "git --work-tree=%s --git-dir=%s init" +GIT_INIT_CHMOD = "chmod og-rwx %s" +GIT_INIT_ADD = "git --work-tree=%s --git-dir=%s add ." +GIT_INIT_COMMIT = "git --work-tree=%s --git-dir=%s commit -m 'automatic import after git-init'" +GIT_COMMIT = "git --work-tree=%s --git-dir=%s commit %s" # We need a secure scratch dir and python does silly verbose errors on the use of tempnam oldmask = os.umask(0077) @@ -82,6 +87,32 @@ else: self.options["log-file"] = "/dev/null" + if not self.options.has_key("use-git"): + self.options['use-git'] = 'no' + if not self.options.has_key("use-rcs"): + self.options['use-rcs'] = 'no' + + if self.options['use-git'] == 'yes' and self.options['use-rcs'] == 'yes': + print >> sys.stderr, \ + 'dispatch-conf: cannot use git and rcs at the same time and " + \ + "use-rcs=yes and use-git=yes in config; fatal' + return False + + if self.options['use-git'] == 'yes': + if not find_binary("git"): + print >> sys.stderr, \ + 'dispatch-conf: Error finding git and " + \ + "use-git=yes in config; fatal' + return False + + if self.options['use-rcs'] == 'yes': + for rcs_util in ("rcs", "ci", "co", "rcsmerge"): + if not find_binary(rcs_util): + print >> sys.stderr, \ + 'dispatch-conf: Error finding all RCS utils and " + \ + "use-rcs=yes in config; fatal' + return False + # # Build list of extant configs # @@ -98,6 +129,20 @@ path, basename = os.path.split(path) find_opts = "-maxdepth 1" + if self.options['use-git'] == 'yes': + dotgit = os.path.join(path, '.git') + if os.path.exists(dotgit): + if not os.path.isdir(dotgit): + print >> sys.stderr, \ + 'dispatch-conf: ' + dotgit + ' is not a git repository; fatal' + return False + else: + os.system(GIT_INIT_DB % (path, dotgit)) + os.system(GIT_INIT_CHMOD % (dotgit,)) + os.system(GIT_INIT_ADD % (path, dotgit)) + os.system(GIT_INIT_COMMIT % (path, dotgit)) + + confs += self.massage(os.popen(FIND_EXTANT_CONFIGS % (path, find_opts, basename)).readlines()) if self.options['use-rcs'] == 'yes': @@ -126,7 +171,7 @@ archive = os.path.join(self.options['archive-dir'], conf['current'].lstrip('/')) if self.options['use-rcs'] == 'yes': mrgfail = portage.dispatch_conf.rcs_archive(archive, conf['current'], conf['new'], mrgconf) - else: + elif self.options['use-git'] == 'no': mrgfail = portage.dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf) if os.path.exists(archive + '.dist'): unmodified = len(commands.getoutput(DIFF_CONTENTS % (conf['current'], archive + '.dist'))) == 0 @@ -313,10 +358,40 @@ archive = os.path.join(self.options['archive-dir'], curconf.lstrip('/')) if self.options['use-rcs'] == 'yes': portage.dispatch_conf.rcs_archive_post_process(archive) + elif self.options['use-git'] == 'yes': + portage.dispatch_conf.git_archive_post_process(curconf) else: portage.dispatch_conf.file_archive_post_process(archive) + def commit(self, config_paths): + """Commit all changed files in CONFIG_PROTECT to the git index""" + if self.options['use-git'] == 'no': + return + + gitopts = "" + if self.options.has_key("git-autocommit") and self.options['git-autocommit'] == 'yes': + gitopts = '-m "automatic commit after dispatch-conf"' + else: + gitopts = '--interactive' + + for path in config_paths.split (): + path = portage.normalize_path(path) + try: + mymode = os.stat(path).st_mode + except OSError: + continue + basename = "" + if not stat.S_ISDIR(mymode): + path, basename = os.path.split(path) + + dotgit = os.path.join(path, '.git') + + print '\n>> Committing changes to %s:' % (path,) + if os.system(GIT_COMMIT % (path, dotgit, gitopts)) == 0: + clear_screen() + + def massage (self, newconfigs): """Sort, rstrip, remove old versions, break into triad hash. @@ -411,8 +486,11 @@ # run d = dispatch () +config_paths = portage.settings ['CONFIG_PROTECT'] + if len(sys.argv) > 1: # for testing - d.grind (" ".join(sys.argv[1:])) -else: - d.grind (portage.settings ['CONFIG_PROTECT']) + config_paths = " ".join(sys.argv[1:]) + +d.grind(config_paths) +d.commit(config_paths) Only in git_portage/bin: dispatch-conf.orig diff -ru orig_portage/cnf/dispatch-conf.conf git_portage/cnf/dispatch-conf.conf --- orig_portage/cnf/dispatch-conf.conf 2007-09-25 00:15:16.000000000 +0200 +++ git_portage/cnf/dispatch-conf.conf 2009-02-28 15:25:09.000000000 +0100 @@ -9,6 +9,14 @@ # (yes or no) use-rcs=no +# Use git for tracking file history in a git database? +# (yes or no) +use-git=no + +# Do an automatic commit or interactive commit? +# (yes or no) +git-autocommit=yes + # Diff for display # %s old file # %s new file diff -ru orig_portage/pym/portage/dispatch_conf.py git_portage/pym/portage/dispatch_conf.py --- orig_portage/pym/portage/dispatch_conf.py 2008-07-01 14:38:49.000000000 +0200 +++ git_portage/pym/portage/dispatch_conf.py 2009-02-28 15:25:09.000000000 +0100 @@ -18,6 +18,8 @@ RCS_GET = 'co' RCS_MERGE = "rcsmerge -p -r" + RCS_BRANCH + " '%s' > '%s'" +GIT_ADD = 'git add %s' + DIFF3_MERGE = "diff3 -mE '%s' '%s' '%s' > '%s'" def read_config(mandatory_opts): @@ -159,3 +161,10 @@ def file_archive_post_process(archive): """Rename the archive file with the .dist.new suffix to a .dist suffix""" os.rename(archive + '.dist.new', archive + '.dist') + +def git_archive_post_process(curconf): + """Add current config file to git for commit""" + curdir = os.getcwd() + os.chdir(os.path.dirname(curconf)) + os.system(GIT_ADD % curconf) + os.chdir(curdir)