Hi all,

Please find attached the patch of the prefix repoman sources against the
current trunk.  I hope I removed all hunks that have prefix-only
changes.

The current diff is mainly SVN support for Repoman.  I extracted the SVN
diffs only.  Most of the original work was done by Kito, and recently I
wiped the dust off of it, and finalised it into some working version.
So far the good news, the bad news now regarding this patch: I had to
somehow hardcode the svn repo being used, as I didn't find a way to let
repoman figure out dynamically what the "offset" in the SVN repository
is where the portage tree starts.  This is kind of similar to how CVS
support is done, where this offset is also hardcoded.

While I think repoman's CVS support has always been used as-is --
nowadays people prefer to start non-CVS repos, the SVN support as in
this patch would, considering the many overlays in SVN around, surely
benefit from some sort of solution that allows to set the "repository
offset" or something, e.g. through a variable.  Thoughts?


-- 
Fabian Groffen
Gentoo on a different level
--- ../../trunk/bin/repoman     2006-11-23 18:15:36 +0100
+++ bin/repoman 2006-11-20 21:52:30 +0100
@@ -407,9 +409,80 @@
                os.environ["FEATURES"]=repoman_settings["FEATURES"]+" cvs"
        isCvs = True
 
-if not "--pretend" in myoptions and not isCvs:
+       try:
+               isCvs=True
+               myrepofile=open("CVS/Repository")
+               myreporoot=myrepofile.readline()[:-1]
+               myrepofile.close()
+               myrepofile=open("CVS/Root")
+               myreporootpath=string.split(myrepofile.readline()[:-1], ":")[-1]
+               myrepofile.close()
+               if myreporootpath == myreporoot[:len(myreporootpath)]:
+                       # goofy os x cvs co.
+                       myreporoot = myreporoot[len(myreporootpath):]
+                       while myreporoot and myreporoot[0] == '/':
+                               myreporoot = myreporoot[1:]
+       except SystemExit, e:
+               raise  # Need to propogate this
+       except:
+               err("Error grabbing repository information; exiting.")
+       myreporootpath=os.path.normpath(myreporootpath)
+       if myreporootpath=="/space/cvsroot":
+               print
+               print
+               print red("You're using the wrong cvsroot. For Manifests to be 
correct, you must")
+               print red("use the same base cvsroot path that the servers use. 
Please try the")
+               print red("following script to remedy this:")
+               print
+               print "cd my_cvs_tree"
+               print
+               print "rm -Rf [a-z]*"
+               print "cvs up"
+               print
+               if portage.userland=="BSD" or portage.userland=="Darwin":
+                       print "find ./ -type f -regex '.*/CVS/Root$' -print0 | 
xargs -0 sed \\"
+               else:
+                       print "find ./ -type f -regex '.*/CVS/Root$' -print0 | 
xargs -0r sed \\"
+               fi
+               print "  -i 's:/space/cvsroot$:/home/cvsroot:'"
+               print
+               print red("You must clear and re-update your tree as all header 
tags will cause")
+               print red("problems in manifests for all rsync and 
/home/cvsroot users.")
+               print
+               print "You should do this to any other gentoo trees your have 
as well,"
+               print "excluding the deletions. 'gentoo-src' should be 
/home/cvsroot."
+               print
+               sys.exit(123)
+
+isSvn=False
+myreporoot=None
+if os.path.isdir(".svn"):
+       if "svn" not in repoman_settings.features:
+               print
+               print
+               print red('!!! You do not have ')+bold('FEATURES="svn" 
')+red("enabled...")
+               print red("!!! ")+bold("Adding \"svn\" to FEATURES")
+               print
+               os.environ["FEATURES"]=repoman_settings["FEATURES"]+" svn"
+
+       try:
+               isSvn=True
+               myrepoinfo = os.popen("svn info").readlines()
+               myurl = myrepoinfo[1][5:].rstrip()
+               myreproot = myrepoinfo[2][17:].rstrip()
+               # This one is EVIL, but I don't know how to solve the problem of
+               # getting rid of /trunk/prefix-overlay.  This only works on the
+               # prefix overlay.
+               myreporoot = "/".join(myurl[len(myreproot):].split("/")[2:])
+               myreporootpath = "/" + "/".join(myreproot.split("/")[3:])
+       except SystemExit, e:
+               raise  # Need to propogate this
+       except:
+               err("Error grabbing repository information; exiting.")
+
+if not "--pretend" in myoptions and not isCvs and not isSvn:
        print
-       print darkgreen("Not in a CVS repository; enabling pretend mode.")
+       print darkgreen("Not in a CVS or SVN repository; enabling pretend 
mode.")
        myoptions.append("--pretend");
 
 
@@ -490,14 +563,17 @@
        myreporoot = os.path.basename(portdir_overlay)
        myreporoot += mydir[len(portdir_overlay):-1]
 
-reposplit=string.split(myreporoot,"/")
+if isSvn:
+       reposplit=string.split(myreporoot,"/")
+else:
+       reposplit=string.split(myreporoot,"/")
 repolevel=len(reposplit)
 
 # check if it's in $PORTDIR/$CATEGORY/$PN , otherwise bail if commiting.
 # Reason for this is if they're trying to commit in just $FILESDIR/*, the 
Manifest needs updating.
 # this check ensure that repoman knows where it is, and the manifest recommit 
is at least possible.
 if mymode == "commit" and repolevel not in [1,2,3]:
-       print red("***")+" Commit attempts *must* be from within a cvs co, 
category, or package directory."
+       print red("***")+" Commit attempts *must* be from within a cvs or svn 
co, category, or package directory."
        print red("***")+" Attempting to commit from a packages files directory 
will be blocked for instance."
        print red("***")+" This is intended behaviour, to ensure the manifest 
is recommited for a package."
        print red("***")
@@ -775,7 +851,7 @@
                                s = s[s.rfind("\n") + 1:]
                        fails["file.UTF8"].append("%s/%s: line %i, just after: 
'%s'" % (checkdir, y, line, s))
 
-       if isCvs:
+       if isCvs or isSvn:
                try:
                        mystat=os.stat(checkdir+"/files")[0]
                        if len(ebuildlist) and not S_ISDIR(mystat):
@@ -787,37 +863,83 @@
                        fails["filedir.missing"].append(checkdir)
                        continue
                try:
-                       myf=open(checkdir+"/CVS/Entries","r")
-                       myl=myf.readlines()
+                       if isCvs:
+                               myf=open(checkdir+"/CVS/Entries","r")
+                       if isSvn:
+                               myf=os.popen("svn update > /dev/null; svn list")
+                       myl=myf.readlines()     
+                       myf.close()
                        for l in myl:
-                               if l[0]!="/":
-                                       continue
-                               splitl=l[1:].split("/")
-                               if not len(splitl):
-                                       continue
-                               if splitl[0][-7:]==".ebuild":
-                                       eadded.append(splitl[0][:-7])
+                               if isCvs:
+                                       if l[0]!="/":
+                                               continue
+                                       splitl=l[1:].split("/")
+                                       if not len(splitl):
+                                               continue
+                                       if splitl[0][-7:]==".ebuild":
+                                               eadded.append(splitl[0][:-7])
+                               if isSvn:
+                                       l = l.rstrip();
+                                       if l[-1:] == "/":
+                                               continue
+                                       if l[-7:] == ".ebuild":
+                                               eadded.append(l[:-7])
+                       if isSvn:
+                               myf=os.popen("svn status")
+                               myl=myf.readlines()
+                               myf.close()
+                               for l in myl:
+                                       if l[0] == "A":
+                                               l = l.rstrip().split(' ')[-1]
+                                               if l[-7:] == ".ebuild":
+                                                       eadded.append(l[:-7])
                except IOError:
-                       if mymode=="commit":
+                       if mymode=="commit" and isCvs:
                                stats["CVS/Entries.IO_error"] += 1
                                
fails["CVS/Entries.IO_error"].append(checkdir+"/CVS/Entries")
+                       if mymode=="commit" and isSvn:
+                               stats["svn.IO_error"] += 1
+                               fails["svn.IO_error"].append(checkdir+"svn 
info")
                        continue
 
                try:
-                       myf=open(checkdir+"/files/CVS/Entries","r")
+                       if isCvs:
+                               myf=open(checkdir+"/files/CVS/Entries","r")
+                       if isSvn:
+                               myf=os.popen("svn list 
"+os.path.normpath(checkdir+"/files"))
                        myl=myf.readlines()
+                       myf.close()
                        for l in myl:
-                               if l[0]!="/":
-                                       continue
-                               splitl=l[1:].split("/")
-                               if not len(splitl):
-                                       continue
-                               if splitl[0][:7]=="digest-":
-                                       dadded.append(splitl[0][7:])
+                               if isCvs:
+                                       if l[0]!="/":
+                                               continue
+                                       splitl=l[1:].split("/")
+                                       if not len(splitl):
+                                               continue
+                                       if splitl[0][:7]=="digest-":
+                                               dadded.append(splitl[0][7:])
+                               if isSvn:
+                                       l = l.rstrip();
+                                       if l[-1:] == "/":
+                                               continue
+                                       if l[:7] == "digest-":
+                                               dadded.append(l[7:])
+                       if isSvn:
+                               myf=os.popen("svn status 
"+os.path.normpath(checkdir+"/files"))
+                               myl=myf.readlines()
+                               myf.close()
+                               for l in myl:
+                                       if l[0] == "A":
+                                               l = l.rstrip().split(' ')[-1]
+                                               if l[:7] == "digest-":
+                                                       dadded.append(l[7:])
                except IOError:
-                       if mymode=="commit":
+                       if mymode=="commit" and isCvs:
                                stats["CVS/Entries.IO_error"] += 1
                                
fails["CVS/Entries.IO_error"].append(checkdir+"/files/CVS/Entries")
+                       if mymode=="commit" and isSvn:
+                               stats["svn.IO_error"] += 1
+                               fails["svn.IO_error"].append(checkdir+"/files 
svn info")
                        continue
 
        if mymode == "commit":
@@ -834,7 +956,7 @@
                for y in filesdirlist:
                        if y[:7]=="digest-":
                                if y[7:] not in dadded:
-                                       #digest not added to cvs
+                                       #digest not added to cvs or svn
                                        
stats["digest.notadded"]=stats["digest.notadded"]+1
                                        
fails["digest.notadded"].append(x+"/files/"+y)
                                        if y[7:] in eadded:
@@ -849,10 +971,14 @@
                                if y[7:] not in ebuildlist:
                                        #stray digest
                                        if mymode=="fix":
+                                               if isCvs:
+                                                       vcsrm="cvs rm -f"
+                                               if isSvn:
+                                                       vcsrm="svn rm --force"
                                                if "--pretend" in myoptions:
-                                                       print "(cd 
"+repodir+"/"+x+"/files; cvs rm -f "+y+")"
+                                                               print "(cd 
"+repodir+"/"+x+"/files; "+vcsrm+" "+y+")"
                                                else:
-                                                       os.system("(cd 
"+repodir+"/"+x+"/files; cvs rm -f "+y+")")
+                                                       os.system("(cd 
"+repodir+"/"+x+"/files; "+vcsrm+" "+y+")")
                                        else:
                                                
stats["digest.stray"]=stats["digest.stray"]+1
                                                
fails["digest.stray"].append(x+"/files/"+y)
@@ -907,10 +1033,10 @@
                                else:
                                        raise oe
                        if S_ISDIR(mystat.st_mode):
-                               if y == "CVS":
+                               if y == "CVS" or y == ".svn":
                                        continue
                                for z in os.listdir(checkdir+"/files/"+y):
-                                       if z == "CVS":
+                                       if z == "CVS" or z == ".svn":
                                                continue
                                        filesdirlist.append(y+"/"+z)
                        # current policy is no files over 20k, this is the 
check.
@@ -966,9 +1092,9 @@
                        if mymode=="fix":
                                if "--pretend" in myoptions:
                                        print "You will need to run:"
-                                       print "  /usr/bin/ebuild 
"+repodir+"/"+x+"/"+y+".ebuild digest"
+                                       print "  
"+portage_const.PORTAGE_BASE+"/bin/ebuild "+repodir+"/"+x+"/"+y+".ebuild digest"
                                else:
-                                       retval=os.system("/usr/bin/ebuild 
"+repodir+"/"+x+"/"+y+".ebuild digest")
+                                       
retval=os.system(portage_const.PORTAGE_BASE+"/bin/ebuild 
"+repodir+"/"+x+"/"+y+".ebuild digest")
                                        if retval:
                                                print "!!! Exiting on ebuild 
digest (shell) error code:",retval
                                                sys.exit(retval)
@@ -1218,7 +1344,7 @@
                                                        
fails[mykey].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+repr(mydep[1]))
 
                # this check needs work, it won't catch (\ndie)
-               if not os.system("egrep '^[^#]*\([^)]*\<die\>' 
"+checkdir+"/"+y+".ebuild >/dev/null 2>&1"):
+               if not os.system(portage_const.EPREFIX+"/usr/bin/grep -E 
'^[^#]*\([^)]*\<die\>' "+checkdir+"/"+y+".ebuild >/dev/null 2>&1"):
                        stats["ebuild.nesteddie"]=stats["ebuild.nesteddie"]+1
                        fails["ebuild.nesteddie"].append(x+"/"+y+".ebuild")
                # uselist checks - global
@@ -1390,7 +1518,7 @@
 #dofull will be set if we should print a "repoman full" informational message
 dofull=0
 for x in qacats:
-       if not isCvs and (string.find(x, "notadded") != -1):
+       if not isCvs and not isSvn and (string.find(x, "notadded") != -1):
                stats[x] = 0
        if stats[x]:
                dowarn=1
@@ -1469,12 +1597,23 @@
                                print "!!! Exiting on ebuild digest (shell) 
error code:",retval
                                sys.exit(retval)
 
-       mycvstree=cvstree.getentries("./",recursive=1)
-       if isCvs and not mycvstree:
-               print "!!! It seems we don't have a cvs tree?"
-               sys.exit(3)
+       if isCvs:
+               try:
+                       myvcstree=cvstree.getentries("./",recursive=1)
+                       
myunadded=cvstree.findunadded(myvcstree,recursive=1,basedir="./")
+               except SystemExit, e:
+                       raise  # TODO propogate this
+               except:
+                       err("Error retrieving CVS tree; exiting.")
 
-       myunadded=cvstree.findunadded(mycvstree,recursive=1,basedir="./")
+       if isSvn:
+               try:
+                       svnstatus=os.popen("svn status").readlines()
+                       myunadded = [ "./"+elem.rstrip().split()[1] for elem in 
svnstatus if elem.startswith("?") ]     
+               except SystemExit, e:
+                       raise  # TODO propogate this
+               except:
+                       err("Error retrieving SVN info; exiting.")
        myautoadd=[]
        if myunadded:
                for x in range(len(myunadded)-1,-1,-1):
@@ -1498,17 +1637,23 @@
        if myautoadd:
                print ">>> Auto-Adding missing digests..."
                if "--pretend" in myoptions:
-                       print "(/usr/bin/cvs add "+string.join(myautoadd)+")"
+                       if isCvs:
+                               print "(cvs add "+string.join(myautoadd)+")"
+                       if isSvn:
+                               print "(svn add "+string.join(myautoadd)+")"
                        retval=0
                else:
-                       retval=os.system("/usr/bin/cvs add 
"+string.join(myautoadd))
+                       if isCvs:
+                               retval=os.system("cvs add 
"+string.join(myautoadd))
+                       if isSvn:
+                               retval=os.system("svn add 
"+string.join(myautoadd))
                if retval:
-                       print "!!! Exiting on cvs (shell) error code:",retval
+                       print "!!! Exiting on vcs (shell) error code:",retval
                        sys.exit(retval)
 
        if myunadded:
-               print red("!!! The following files are in your cvs tree but are 
not added to the master")
-               print red("!!! tree. Please remove them from the cvs tree or 
add them to the master tree.")
+               print red("!!! The following files are in your local tree but 
are not added to the master")
+               print red("!!! tree. Please remove them from the local tree or 
add them to the master tree.")
                for x in myunadded:
                        print "   ",x
                print
@@ -1518,31 +1663,42 @@
        retval=["",""]
        if isCvs:
                print "Performing a "+green("cvs -n up")+" with a little magic 
grep to check for updates."
-               retval=getstatusoutput("/usr/bin/cvs -n up 2>&1 | egrep '^[^\?] 
.*' | egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'")
-               
+               retval=getstatusoutput(portage_const.EPREFIX+"/usr/bin/cvs -n 
up 2>&1 | "+portage_const.EPREFIX+"/bin/egrep '^[^\?] .*' | 
"+portage_const.EPREFIX+"/bin/egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- 
ignored$'")
+       if isSvn:
+               print "Performing a "+green("svn update -u")+" with a little 
magic grep to check for updates."
+               retval=getstatusoutput(portage_const.EPREFIX+"/usr/bin/svn 
status -u 2>&1 | "+portage_const.EPREFIX+"/bin/egrep -v '^.  +.*/digest-[^/]+' 
| "+portage_const.EPREFIX+"/bin/egrep -v '^Status against revision:'")
+
        mylines=string.split(retval[1], "\n")
        myupdates=[]
        for x in mylines:
                if not x:
                        continue
-               if x[0] not in "UPMAR": # Updates,Patches,Modified,Added,Removed
-                       print red("!!! Please fix the following issues reported 
from cvs: ")+green("(U,P,M,A,R are ok)")
-                       print red("!!! Note: This is a pretend/no-modify 
pass...")
+               if x[0] not in "UPMARD": # 
Updates,Patches,Modified,Added,Removed/Replaced(svn),Deleted(svn)
+                       print red("!!! Please fix the following issues reported 
from cvs: ")+green("(U,P,M,A,R,D are ok)")
+                       if isCvs:
+                               print red("!!! Note: This is a 
pretend/no-modify pass...")
+                       if isSvn:
+                               print red("!!! Note: This your local checkout 
has been modified!")
                        print retval[1]
                        print
                        sys.exit(1)
-               elif x[0] in ["U","P"]:
+               elif isCvs and x[0] in ["U","P"]:
                        myupdates+=[x[2:]]
+               elif isSvn and x[8] == '*':
+                       myupdates+=[x[9:].lstrip(" 1234567890")]
        
        if myupdates:
                print green("Fetching trivial updates...")
                if "--pretend" in myoptions:
-                       print "(/usr/bin/cvs up "+string.join(myupdates)+")"
+                       print "(cvs/svn up "+string.join(myupdates)+")"
                        retval=0
                else:
-                       retval=os.system("/usr/bin/cvs up 
"+string.join(myupdates))
+                       if isCvs:
+                               retval=os.system("cvs up 
"+string.join(myupdates))
+                       elif isSvn:
+                               retval=os.system("svn update 
"+string.join(myupdates))
                if retval!=0:
-                       print "!!! cvs exited with an error. Terminating."
+                       print "!!! cvs/svn exited with an error. Terminating."
                        sys.exit(retval)
        
        if isCvs:
@@ -1552,6 +1708,15 @@
                        mychanged.remove(manifest)
                mynew=cvstree.findnew(mycvstree,recursive=1,basedir="./")
                
myremoved=cvstree.findremoved(mycvstree,recursive=1,basedir="./")
+       if isSvn:
+               svnstatus = os.popen("svn status").readlines()
+               mychanged = [ elem.rstrip()[7:] for elem in svnstatus if 
elem.startswith("M") ]
+               for manifest in [ file for file in mychanged if '/Manifest' in 
file ]:
+                       mychanged.remove(manifest)
+               mynew = [ elem.rstrip()[7:] for elem in svnstatus if 
elem.startswith("A") ]
+               myremoved = [ elem.rstrip()[7:] for elem in svnstatus if 
elem.startswith("D") ]
+
+       if isCvs or isSvn:
                if not (mychanged or mynew or myremoved):
                        print
                        print green("RepoMan sez:"), "\"Doing nothing is not 
always good for QA.\"\n"
@@ -1590,15 +1755,20 @@
                                raise
                # We've read the content so the file is no longer needed.
                commitmessagefile = None
-       if not commitmessage:
-               print "Please enter a CVS commit message at the prompt:"
+       
+       if not (commitmessage or commitmessagefile):
+               print "Please enter a commit message at the prompt:"
                while not commitmessage:
                        try:
                                commitmessage=raw_input(green("> "))
                        except KeyboardInterrupt: 
                                exithandler()
        try:
-               commitmessage+="\n(Portage version: "+str(portage.VERSION)+")"
+               commitmessage+="\n(Portage version: 
"+str(portage.VERSION)+"-prefix/Repoman-"
+               if isCvs:
+                       commitmessage+="CVS)"
+               elif isSvn:
+                       commitmessage+="SVN)"
        except AttributeError:
                print "Failed to insert portage version in message!"
                commitmessage+="\n(Portage version: Unknown)"
@@ -1620,12 +1790,19 @@
 
                retval = None
                if "--pretend" in myoptions:
-                       print "(/usr/bin/cvs -q commit -F "+ commitmessagefile 
+" "+ string.join(myupdates," ")+")"
+                       if isCvs:
+                               print "(cvs -q commit -F "+commitmessagefile+")"
+                       if isSvn:
+                               print "(svn commit -F "+commitmessagefile+")"
+                       retval=0
                else:
-                       retval=os.system("/usr/bin/cvs -q commit -F "+ 
commitmessagefile + " " +string.join(myupdates, " "))
-                       if retval:
-                               print "!!! Exiting on cvs (shell) error 
code:",retval
-                               sys.exit(retval)
+                       if isCvs:
+                               retval=os.system("cvs -q commit -F 
"+commitmessagefile)
+                       if isSvn:
+                               retval=os.system("svn commit -F 
"+commitmessagefile)
+               if retval:
+                       print "!!! Exiting on vcs (shell) error code:",retval
+                       sys.exit(retval)
 
        # Setup the GPG commands
        def gpgsign(filename):
@@ -1700,13 +1877,13 @@
                # Force an unsigned commit when more than one Manifest needs to 
be signed.
                if repolevel < 3 and "sign" in repoman_settings.features:
                        if "--pretend" in myoptions:
-                               print "(/usr/bin/cvs -q commit -F 
"+commitmessagefile+")"
+                               print "(cvs -q commit -F "+commitmessagefile+")"
                        else:
                                mymsg=open(commitmessagefile,"w")
                                mymsg.write(commitmessage)
                                mymsg.write("\n (Unsigned Manifest commit)")
                                mymsg.close()
-                               retval=os.system("/usr/bin/cvs -q commit -F 
"+commitmessagefile)
+                               retval=os.system("cvs -q commit -F 
"+commitmessagefile)
                                if retval:
                                        print "!!! Exiting on cvs (shell) error 
code:",retval
                                        sys.exit(retval)
@@ -1750,7 +1927,10 @@
 
        if need_commit or signed:
                if "--pretend" in myoptions:
-                       print "(/usr/bin/cvs -q commit -F 
"+commitmessagefile+")"
+                       if isCvs:
+                               print "(cvs -q commit -F "+commitmessagefile+")"
+                       if isSvn:
+                               print "(svn -q commit -F "+commitmessagefile+")"
                else:
                        mymsg=open(commitmessagefile,"w")
                        mymsg.write(commitmessage)
@@ -1759,7 +1939,10 @@
                        else:
                                mymsg.write("\n (Unsigned Manifest commit)")
                        mymsg.close()
-                       retval=os.system("/usr/bin/cvs -q commit -F 
"+commitmessagefile)
+                       if isCvs:
+                               retval=os.system("cvs -q commit -F 
"+commitmessagefile)
+                       if isSvn:
+                               retval=os.system("svn -q commit -F 
"+commitmessagefile)
                        if retval:
                                print "!!! Exiting on cvs (shell) error 
code:",retval
                                sys.exit(retval)
@@ -1767,10 +1950,10 @@
        if unlinkfile:
                os.unlink(commitmessagefile)
        print
-       if isCvs:
-               print "CVS commit complete."
+       if isCvs or isSvn:
+               print "Commit complete."
        else:
-               print "repoman was too scared by not seeing any familiar cvs 
file that he forgot to commit anything"
+               print "repoman was too scared by not seeing any familiar 
version control file that he forgot to commit anything"
        print green("RepoMan sez:"), "\"If everyone were like you, I'd be out 
of business!\"\n"
 sys.exit(0)
 

Reply via email to