cvs2svn-migration/trunk: . README builder invoke_cvs2svn macros
migrator
saq
cvs at pld-linux.org
Tue Sep 13 18:48:33 CEST 2005
Author: saq
Date: Tue Sep 13 18:48:27 2005
New Revision: 6373
Added:
cvs2svn-migration/trunk/
cvs2svn-migration/trunk/README
cvs2svn-migration/trunk/builder (contents, props changed)
cvs2svn-migration/trunk/invoke_cvs2svn (contents, props changed)
cvs2svn-migration/trunk/macros
cvs2svn-migration/trunk/migrator (contents, props changed)
Log:
- initial checkin
Added: cvs2svn-migration/trunk/README
==============================================================================
--- (empty file)
+++ cvs2svn-migration/trunk/README Tue Sep 13 18:48:27 2005
@@ -0,0 +1,70 @@
+===
+
+Steps to migrate the PLD repo cvs->svn
+
+1. Disable write access to the CVS repo
+2. Use migrator to reorganize the repo according to the dir-per-package scheme
+3. Perform some manual clean-ups.
+4. Use cvs2svn to generate svn entries and revisions.
+5. Perform some manual clean-ups.
+6. Celebrate.
+
+After step 3 you can try working with CVS on the new structure (read-only),
+you will have to `mkdir CVSROOT` for that.
+
+===
+
+migrator quick docs
+
+What it does: creates a copy of the existing PLD repo (or its rsync copy),
+reorganizing the files on the fly. The result is a flat structure: each
+package has a directory of its own, S{PEC,OURCE}S are no more. Don't worry
+about disk space, it's a cheap (hardlink-based) copy. Do place the source
+and target on the same filesystem.
+
+For configuration, see the sources. For testing purposes you can limit
+yourself to a subset of the specs; again, see the sources.
+
+A source is considered to belong to a given package if it's a Source or a
+Patch of at least one revision of a given foo.spec,v (malformed revisions
+are discarded). rpm parsing of each single release is probably the most
+costly operation. Converting a*.spec took 30 minutes.
+
+The above rule means that if a source belongs to various specs, it will
+get duplicated in the resulting repo. Sources which don't belong anywhere
+go to a common directory (that is, no file gets omitted, except for files
+that weren't valid CVS-controlled files in the first place).
+
+===
+
+migrator open issues:
+
+- There are files in SPECS which aren't valid specs (builder,v for
+ example). Find a cosy place for them.
+- There are files in SOURCES which apparently don't belong to any package.
+ Find a good place for them (bitbucket is an option).
+
+===
+
+Other open issues:
+
+- How to write %changelog under svn? What to do with the existing entries?
+- What tasks are necessary in steps 3 and 5 above?
+- What needs to be done to adapt src builder?
+- What about the filter_tags.sh rules?
+- What directory structure for tags and branches? cvs2svn gives:
+trunk/MathReader/MathReader.spec
+tags/auto-ac-MathPlanner-3_1_3-1/MathPlanner/MathPlanner.spec
+branches/RA-branch/MathPlanner/MathPlanner.spec
+
+===
+
+Changes to the development environment:
+
+- topdir/S{PEC,OURCE}S are no more. topdir/{BUILD,{,S}RPMS} will stay there
+- 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
+- builder will never be the same again
+
+===
Added: cvs2svn-migration/trunk/builder
==============================================================================
--- (empty file)
+++ cvs2svn-migration/trunk/builder Tue Sep 13 18:48:27 2005
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+# Note: it's only useful for the conversion proof-of-concept.
+
+# Hint: -r branches/AC-branch or -r tags/auto-ac-bofh-0_2-4
+
+SVNROOT="file:///home/users/saq/tmp/svn"
+TAGDIR="trunk"
+PACKAGE=""
+
+BUILD="yes"
+
+while test $# -gt 0; do
+ case "$1" in
+ -g )
+ BUILD="no";shift;;
+ -r )
+ TAGDIR="$2";shift;shift;;
+ * )
+ PACKAGE="$1";shift;;
+ esac
+done
+if [ "$PACKAGE" = "" ]; then
+ echo "Usage: builder [-g] [-r foo] package"
+ exit 1
+fi
+cd $(rpmbuild --eval %_topdir 2>/dev/null)
+svn co $SVNROOT/$TAGDIR/$PACKAGE
+cd $PACKAGE
+dump="$(rpmbuild --nodigest --nosignature --nodeps --define 'prep %dump' $PACKAGE.spec 2>&1)"
+source0url=$(echo "$dump"|awk '/SOURCEURL0/ {print $3}')
+source0=$(echo "$dump"|awk '/SOURCE0/ {print $3}')
+#echo S $source0url $source0
+have_md5=$(md5sum $source0|awk '{print $1}')
+need_md5=$(cat $PACKAGE.spec|awk '/ Source0-md5/{print $3}')
+#echo M $have_md5 $need_md5
+if [ "$have_md5" != "$need_md5" ]; then
+ rm -f $source0
+ wget http://distfiles.pld-linux.org/by-md5/$(echo $need_md5|sed -e 's|^\(.\)\(.\)|\1/\2/&|')/$(basename $source0)
+fi
+if [ "$BUILD" = "yes" ]; then
+ rpmbuild -bb $PACKAGE.spec
+fi
Added: cvs2svn-migration/trunk/invoke_cvs2svn
==============================================================================
--- (empty file)
+++ cvs2svn-migration/trunk/invoke_cvs2svn Tue Sep 13 18:48:27 2005
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+OPTS="--encoding=ISO-8859-2"
+
+# Checking for tag/branch mismatches...
+# ERROR: The following symbols are tags in some files and branches in others.
+# yees, the beauty of PLD
+OPTS="$OPTS --force-branch=DEVEL --force-branch=RA-branch --force-branch=AC-branch"
+OPTS="$OPTS --force-branch=RA-branch_general"
+OPTS="$OPTS --force-branch=LINUX_2_6 --force-branch=LINUX_2_4 --force-branch=LINUX_2_2_DEVEL"
+OPTS="$OPTS --force-branch=GNOME_2_0 --force-branch=rpm3"
+# you'll find many others
+
+exec cvs2svn $OPTS -s /home/users/saq/tmp/svn /home/users/saq/tmp/repo
Added: cvs2svn-migration/trunk/macros
==============================================================================
--- (empty file)
+++ cvs2svn-migration/trunk/macros Tue Sep 13 18:48:27 2005
@@ -0,0 +1,7 @@
+# The macros that need to be modified. Not a very long list.
+
+# A cool feature: rpmbuild --rebuild foo...src.rpm mkdirs those if they
+# don't exist
+
+%_sourcedir %{_topdir}/%{name}
+%_specdir %{_topdir}/%{name}
Added: cvs2svn-migration/trunk/migrator
==============================================================================
--- (empty file)
+++ cvs2svn-migration/trunk/migrator Tue Sep 13 18:48:27 2005
@@ -0,0 +1,164 @@
+#!/usr/bin/python
+
+# requires: cvs2svn, rcs, rpm-build
+
+# source
+cvsdir="/home/users/saq/PLD/repo"
+# target
+tmpcvsdir="/home/users/saq/tmp/repo"
+# rpm can't read a spec from stdin
+tmpspecfile="/home/users/saq/tmp/foo.spec"
+# reasons of failures
+logdir="/home/users/saq/tmp/migrator-log"
+
+# only those SPECS/ files will be copied
+spec_re="^c.*"
+#spec_re=".*"
+# only those SOURCES/ files will be considered for SOURCES.old
+# (files for specs are sought among all sources)
+source_re="^c.*"
+#source_re=".*"
+
+# internals follow
+
+import cvs2svn_rcsparse
+import os
+import re
+from subprocess import Popen,PIPE
+
+spec_re=re.compile(spec_re)
+source_re=re.compile(source_re)
+
+def cvspackagedir(package):
+ dir=tmpcvsdir+"/"+package
+ return dir
+
+specsdir=cvsdir+"/SPECS"
+sourcesdir=cvsdir+"/SOURCES"
+specsolddir=tmpcvsdir+"/SPECS.old"
+sourcesolddir=tmpcvsdir+"/SOURCES.old"
+
+# utilities
+
+class Sink(cvs2svn_rcsparse.Sink):
+ def __init__(self):
+ self.revs=[]
+ def define_revision(self,rev,*args):
+ self.revs.append(rev)
+
+def get_revisions(f):
+ """Get all revision numbers from a ,v file"""
+ sink=Sink()
+ cvs2svn_rcsparse.parse(f,sink)
+ return sink.revs
+
+def mkdir(dir):
+ # might exist already
+ try:
+ os.makedirs(dir)
+ except OSError:
+ pass
+
+def ln(oldpath,newdir):
+ lastdir,file=oldpath.split("/")[-2:]
+ if lastdir=="Attic": newdir+="/Attic"
+ newpath="%s/%s"%(newdir,file)
+ # the noble exception of nps.spec
+ try:
+ link=os.readlink(oldpath)
+ oldpath+="/"+link
+ except OSError:
+ # not a symlink
+ pass
+ os.link(oldpath,newpath)
+
+def listdir(dir):
+ """For a given CVS module directory, get a mapping:
+ version controlled file->path to its ,v"""
+ # ERROR: A CVS repository cannot contain both /tmp/cvs/SPECS/Mis.spec,v and /tmp/cvs/SPECS/Attic/Mis.spec,v
+ # PLD has always been exceptional :)
+ # Having no better idea, discard the Attic version. As well as all non-,v files.
+ livefiles=os.listdir(dir)
+ atticfiles=os.listdir(dir+"/Attic")
+ files={}
+ for f in atticfiles:
+ if not f.endswith(",v"): continue
+ files[f[:-2]]="%s/Attic/%s"%(dir,f)
+ for f in livefiles:
+ if not f.endswith(",v"): continue
+ files[f[:-2]]="%s/%s"%(dir,f)
+ return files
+
+def spec2sources(f):
+ """
+ Get a sequence of the sources that belong to the given spec.
+ This means checking each revision to follow the sources' list changes.
+ """
+ assert f.endswith(",v")
+ all_sources=set()
+ for rev in get_revisions(file(f)):
+ # This part would have been easier in another language
+ p1=Popen(["co","-p","-r"+rev,f[:-2]],stdout=PIPE,stderr=file("/dev/null","w"))
+ # post-processing to maximize the chance of a successful parse
+ p2=Popen(["sed",r"/^Icon:/d;/^Serial:/d;/^%define.*_kernel_ver/d;s/^Copyright:/License:/"],
+ stdin=p1.stdout,stdout=file(tmpspecfile,"w")
+ )
+ if p1.wait()!=0 or p2.wait()!=0:
+ print "WARN: %s@%s: checkout failed"%(f,rev)
+ continue
+
+ cmd1=["rpmbuild","--nodigest","--nosignature","--nodeps",
+ "--define","_kernel_ver_str 2.0.28",
+ "--define","prep %dump",tmpspecfile]
+ p1=Popen(cmd1,stderr=PIPE)
+ p2=Popen(["awk",'/SOURCE[0-9]+|PATCH[0-9]+/ {sub(".*/","",$3);print $3}'],stdin=p1.stderr,stdout=PIPE)
+ # strip trailing \n
+ sources=[line[:-1] for line in p2.stdout]
+ if p1.wait()!=0 or p2.wait()!=0:
+ what="%s@%s"%(f.split('/')[-1],rev)
+ print "WARN: %s: unable to parse, see log for details"%(what,)
+ Popen(cmd1,stderr=file("%s/%s.log"%(logdir,what),"w")).wait()
+ continue
+ all_sources.update(sources)
+ return all_sources
+
+# let's go
+
+specs_all=listdir(specsdir)
+specs_used=set()
+sources_all=listdir(sourcesdir)
+sources_used=set()
+
+print "0. Cleanup"
+os.system("rm -rf %s"%(tmpcvsdir,))
+os.system("rm -rf %s"%(logdir,))
+mkdir(logdir)
+
+print "1. Reorganizing CVS repo"
+for spec,path in specs_all.iteritems():
+ if spec_re.match(spec) is None: continue
+ if not spec.endswith(".spec"):
+ print "WARN: what the hell is SPECS/%s?"%(spec,)
+ continue
+ package=spec[:-5]
+ dir=cvspackagedir(package)
+ mkdir(dir+"/Attic")
+ ln(path,dir)
+ sources=spec2sources(path)
+ for source in sources:
+ if not source in sources_all: continue
+ ln(sources_all[source],dir)
+ sources_used.update(sources)
+ specs_used.add(spec)
+
+print "2. Keeping remaining SPECS and SOURCES"
+mkdir(specsolddir+"/Attic")
+mkdir(sourcesolddir+"/Attic")
+for spec,path in specs_all.iteritems():
+ if spec in specs_used: continue
+ if spec_re.match(spec) is None: continue
+ ln(path,specsolddir)
+for source,path in sources_all.iteritems():
+ if source in sources_used: continue
+ if source_re.match(source) is None: continue
+ ln(path,sourcesolddir)
More information about the pld-cvs-commit
mailing list