cvs2svn-migration/trunk: README mirror post_cvs2svn
saq
cvs at pld-linux.org
Sat Oct 8 20:13:47 CEST 2005
Author: saq
Date: Sat Oct 8 20:13:22 2005
New Revision: 6436
Added:
cvs2svn-migration/trunk/mirror (contents, props changed)
Modified:
cvs2svn-migration/trunk/README
cvs2svn-migration/trunk/post_cvs2svn
Log:
- the have-traditional-SPECS hook
Modified: cvs2svn-migration/trunk/README
==============================================================================
--- cvs2svn-migration/trunk/README (original)
+++ cvs2svn-migration/trunk/README Sat Oct 8 20:13:22 2005
@@ -6,7 +6,8 @@
2. Use migrator to reorganize the repo according to the dir-per-package scheme
3. Perform some manual clean-ups.
4. Use invoke_cvs2svn to generate svn entries and revisions.
-5. Use post_cvs2svn to reorganize the repo into $package/{trunk,tags,branches}.
+5. Use post_cvs2svn to install the hooks and reorganize the repo into
+ $package/{trunk,tags,branches}.
6. Perform some manual clean-ups.
7. Celebrate.
@@ -60,7 +61,9 @@
Changes to the development environment:
-- topdir/S{PEC,OURCE}S are no more. topdir/{BUILD,{,S}RPMS} will stay there
+- topdir/SOURCES is no more. topdir/{BUILD,{,S}RPMS} will stay there
+- You can use topdir/SPECS the usual (deprecated) way. It is syncked with
+ the specs placed in packages' dirs.
- topdir/foo looks like the right checkout spot for foo.spec and its sources
- topdir/foo/foo-0.00.tar for distfiles
- need new macros to find the sources in the new place
Added: cvs2svn-migration/trunk/mirror
==============================================================================
--- (empty file)
+++ cvs2svn-migration/trunk/mirror Sat Oct 8 20:13:22 2005
@@ -0,0 +1,178 @@
+#!/usr/bin/python
+
+# SVN change mirrorer
+#
+# To make sure that two different paths in the repo carry the same contents.
+#
+# Usage:
+# $0 repo --pre txn
+# sanity checks
+# $0 repo --post rev
+# actual mirroring (if necessary)
+
+# Known bugs:
+# - removing a spec-containing directory (at any depth) isn't mirrored by
+# removing the spec in the other location
+# - same with moving
+# - maybe SPECS/tags isn't really useful/necessary
+
+import os
+import re
+import sys
+import traceback
+
+from svn import core,fs,delta,repos
+
+# You may call these the "config" if you please
+
+place1_re=re.compile(r"^([^/]*)/(.*)/([^/]*)\.spec") # \1==\3==spec, \2==tag
+def match_place1(path):
+ match=place1_re.match(path)
+ if match is None: return None,None
+ if match.group(1)!=match.group(3): return None,None
+ return match.group(1),match.group(2)
+place2_re=re.compile(r"SPECS/(.*)/([^/]*)\.spec") # \1==tag, \2==spec
+def match_place2(path):
+ match=place2_re.match(path)
+ if match is None: return None,None
+ return match.group(2),match.group(1)
+
+def match_place(path):
+ spec,tag=match_place1(path)
+ if spec is not None: return 1,spec,tag
+ spec,tag=match_place2(path)
+ if spec is not None: return 2,spec,tag
+ return None,None,None
+def locations(spec,tag):
+ return ["%s/%s/%s.spec"%(spec,tag,spec),"SPECS/%s/%s.spec"%(tag,spec)]
+def trust_change(props):
+ log=props('svn:log')
+ author=props('svn:author')
+ # don't mirror mirror commits
+ if author=="mirror": return True
+ # I Know What I'm Doing
+ return author=="saq" and "IKWID" in log
+
+# go
+
+log=file("/home/users/saq/tmp/mirror.log.%d"%(os.getpid(),),"w")
+print >>log,"Starting",sys.argv
+
+class Txn:
+ def __init__(self,repo,rev,uname,commitmsg):
+ self.repo=repo
+ self.txn=repos.fs_begin_txn_for_commit(self.repo.repo,rev,uname,commitmsg,self.repo.pool)
+ self.base_root=self.repo.rev_root(rev)
+ self.root=fs.txn_root(self.txn,self.repo.pool)
+ def delete(self,path):
+ print >>log,"Deleting",path
+ fs.delete(self.root,path,self.repo.pool)
+ def mkdirs(self,path):
+ dir=path.rsplit("/",1)[0]
+ if dir==path: return
+ if fs.check_path(self.root,dir,self.repo.pool)==core.svn_node_none:
+ self.mkdirs(dir)
+ print >>log,"Mkdiring",dir
+ fs.make_dir(self.root,dir,self.repo.pool)
+ def copy(self,path_from,path_to):
+ if path_from==path_to: return
+ if fs.check_path(self.root,path_to,self.repo.pool)!=core.svn_node_none:
+ self.delete(path_to)
+ else:
+ self.mkdirs(path_to)
+ print >>log,"Copying",path_from,"to",path_to
+ fs.copy(self.base_root,path_from,self.root,path_to,self.repo.pool)
+ contents=self.repo.contents(path_from,root=self.root)
+ handler,baton=fs.apply_textdelta(self.root,path_to,None,None,self.repo.pool)
+ delta.svn_txdelta_send_string(contents,handler,baton,self.repo.pool)
+ def commit(self):
+ rev=repos.fs_commit_txn(self.repo.repo,self.txn,self.repo.pool)
+ print >>log,"Committed revision",rev
+
+class Repo:
+ def __init__(self,path,pool):
+ self.repo=repos.open(path,pool)
+ self.fs=repos.fs(self.repo)
+ self.pool=pool
+ self.roots={}
+ def txn_root(self,txn_name):
+ return fs.txn_root(fs.open_txn(self.fs,txn_name,self.pool),self.pool)
+ def rev_root(self,rev_no):
+ try:
+ return self.roots[rev_no]
+ except KeyError:
+ root=fs.revision_root(self.fs,rev_no,self.pool)
+ self.roots[rev_no]=root
+ return root
+ def txn_props(self,txn_name):
+ txn=fs.open_txn(self.fs,txn_name,self.pool)
+ def props(name):
+ return fs.txn_prop(txn,name,self.pool)
+ return props
+ def rev_props(self,rev_no):
+ def props(name):
+ return fs.revision_prop(self.fs,rev_no,name,self.pool)
+ return props
+ def changes(self,root):
+ collector=repos.ChangeCollector(self.fs,root,self.pool)
+ editor,editor_baton=delta.make_editor(collector,self.pool)
+ repos.replay(root,editor,editor_baton,self.pool)
+ return collector.get_changes()
+ def contents(self,path,rev=None,root=None):
+ if root is None:
+ if rev==-1: return None # file never existed
+ root=self.rev_root(rev)
+ subpool=core.svn_pool_create(self.pool)
+ try:
+ stream=core.Stream(fs.file_contents(root,path,subpool))
+ return stream.read()
+ finally:
+ core.svn_pool_destroy(subpool)
+
+def main(pool):
+ repo=Repo(sys.argv[1],pool)
+ if sys.argv[2]=="--pre":
+ root=repo.txn_root(sys.argv[3])
+ props=repo.txn_props(sys.argv[3])
+ mirror=False
+ elif sys.argv[2]=="--post":
+ created_rev=int(sys.argv[3])
+ root=repo.rev_root(created_rev)
+ props=repo.rev_props(created_rev)
+ mirror=True
+ else:
+ sys.exit("Illegal usage")
+ if trust_change(props):
+ print >>log,"This change is trusted, not mangling"
+ return
+ changes={}
+ for path,change in repo.changes(root).iteritems():
+ place,spec,tag=match_place(path)
+ if place is None: continue
+ if (spec,tag) in changes:
+ sys.exit("Two different changes for %s at %s"%(spec,tag))
+ changes[(spec,tag)]=place,change
+ for (spec,tag),(place,change) in changes.iteritems():
+ variants=set([repo.contents(path,rev=change.base_rev) for path in locations(spec,tag)])
+ if len(variants)!=1:
+ sys.exit("Differences before transaction amongst "+repr(locations(spec,tag)))
+ del variants # garbage collect it asap
+ if not mirror: return
+ if len(changes)==0:
+ print >>log,"No changes in specs"
+ return
+ txn=Txn(repo,created_rev,"mirror","- resync")
+ for (spec,tag),(place,change) in changes.iteritems():
+ for path in locations(spec,tag):
+ if change.path is None:
+ if path!=change.base_path: txn.delete(path)
+ else:
+ txn.copy(change.path,path)
+ txn.commit()
+
+try:
+ core.run_app(main)
+except:
+ # TODO mail somebody if this is reached on --post (need manual care)
+ traceback.print_exc(file=log)
+ raise
Modified: cvs2svn-migration/trunk/post_cvs2svn
==============================================================================
--- cvs2svn-migration/trunk/post_cvs2svn (original)
+++ cvs2svn-migration/trunk/post_cvs2svn Sat Oct 8 20:13:22 2005
@@ -41,9 +41,21 @@
echo "$in_tags$in_branches"|tr \ \\n|grep "^$1/[^/]*/$2\$"
}
-ls
+mirror() {
+ if [ "$1" = "SOURCES.old" -o "$1" = "SPECS.old" ]; then
+ return
+ fi
+ SVN mkdir $root/SPECS/$2
+ SVN cp $root/$1/$2/$1.spec $root/SPECS/$2/$1.spec
+}
echo "1. Moving */foo to foo/*"
+echo "If you see that /SPECS/some_dir already exists, that's fine"
+echo "Same with 'some_spec does not exist'"
+# the latter being another sign of the PLD mess
+ls
+
+SVN mkdir $root/SPECS{,/trunk,/tags,/branches}
for pkgdir in $in_trunk $in_tags $in_branches; do
pkg=$(echo $pkgdir|sed s,.*/,,)
pkg_for_var=$(echo $pkg|tr .+- ___)
@@ -54,12 +66,14 @@
SVN mkdir $root/$pkg
if [ "$pkgdir" = "trunk/$pkg" ]; then
SVN mv $root/trunk/$pkg $root/$pkg/trunk
+ mirror $pkg trunk
fi
if have tags $pkg; then
SVN mkdir $root/$pkg/tags
for dir in $(matching tags $pkg); do
name=$(echo $dir|cut -d/ -f2)
SVN mv $root/$dir $root/$pkg/tags/$name
+ mirror $pkg tags/$name
done
fi
if have branches $pkg; then
@@ -67,6 +81,7 @@
for dir in $(matching branches $pkg); do
name=$(echo $dir|cut -d/ -f2)
SVN mv $root/$dir $root/$pkg/branches/$name
+ mirror $pkg branches/$name
done
fi
done
@@ -80,3 +95,16 @@
fi
# damn lucky there are no packages by these names
SVN rm $root/{trunk,tags,branches}
+
+echo "3. Installing hooks"
+cp mirror $svndir/hooks
+cat>$svndir/hooks/pre-commit<<EOF
+#!/bin/sh
+$svndir/hooks/mirror "\$1" --pre "\$2"
+EOF
+cat>$svndir/hooks/post-commit<<EOF
+#!/bin/sh
+$svndir/hooks/mirror "\$1" --post "\$2"
+EOF
+chmod 755 $svndir/hooks/p{re,ost}-commit
+
More information about the pld-cvs-commit
mailing list