Exemplo n.º 1
0
    def execute(self, dumpfilename, directory):
        """
        Executes the export.

        @type dumpfilename: string
        @param dumpfilename: Name of the svn dump file.
        @type directory: string
        @param directory: Directory to store the exported files.
        """

        dump = SvnDumpFile()
        dump.open(dumpfilename)

        while dump.read_next_rev():
            revnr = dump.get_rev_nr()
            if self.__exports.has_key(revnr):
                for path, filename in self.__exports[revnr].iteritems():
                    print "r%-6d %s" % (revnr, path)
                    nodes = dump.get_nodes_by_path(path, "ACR")
                    saved = False
                    for node in nodes:
                        if node.has_text():
                            outfile = open(filename, "wb")
                            node.write_text_to_file(outfile)
                            outfile.close()
                            saved = True
                            print "  saved as %s" % filename
                    if not saved:
                        if len(nodes) == 0:
                            print "  not found"
                        else:
                            print "  has no text"
        dump.close()
        return 0
Exemplo n.º 2
0
    def execute( self, dumpfilename, directory ):
        """
        Executes the export.

        @type dumpfilename: string
        @param dumpfilename: Name of the svn dump file.
        @type directory: string
        @param directory: Directory to store the exported files.
        """

        dump = SvnDumpFile()
        dump.open( dumpfilename )

        while dump.read_next_rev():
            revnr = dump.get_rev_nr()
            if self.__exports.has_key( revnr ):
                for path, filename in self.__exports[revnr].iteritems():
                    print "r%-6d %s" % ( revnr, path )
                    nodes = dump.get_nodes_by_path( path, "ACR" )
                    saved = False
                    for node in nodes:
                        if node.has_text():
                            outfile = open( filename, "wb" )
                            node.write_text_to_file( outfile )
                            outfile.close()
                            saved = True
                            print "  saved as %s" % filename
                    if not saved:
                        if len(nodes) == 0:
                            print "  not found"
                        else:
                            print "  has no text"
        dump.close()
        return 0
Exemplo n.º 3
0
    def old_execute(self, dumpfilename):
        """
        Print file list of a dump file.

        @type dumpfilename: string
        @param dumpfilename: Name of the file to log.
        """

        dump = SvnDumpFile()
        dump.open(dumpfilename)
        actions = {"add": "A", "change": "M", "delete": "D", "replace": "R"}
        lines = ""

        while dump.read_next_rev():
            revnr = dump.get_rev_nr()
            if revnr == self.revNr or self.revNr == -1:
                lines = ""
                for node in dump.get_nodes_iter():
                    action = actions[node.get_action()]
                    path = node.get_path()
                    if path == "" or path[0] != "/":
                        path = "/" + path
                    if node.has_copy_from():
                        fpath = node.get_copy_from_path()
                        frev = node.get_copy_from_rev()
                        if fpath == "" or fpath[0] != "/":
                            fpath = "/" + fpath
                        path += " (from %s:%d)" % (fpath, frev)
                    lines += "   %s %s\n" % (action, path)
                if revnr == self.revNr:
                    print lines,
                    lines = ""
                    break
        if len(lines) > 0:
            print lines,

        dump.close()
        return 0
Exemplo n.º 4
0
    def old_execute( self, dumpfilename ):
        """
        Print file list of a dump file.

        @type dumpfilename: string
        @param dumpfilename: Name of the file to log.
        """

        dump = SvnDumpFile()
        dump.open( dumpfilename )
        actions = { "add":"A", "change":"M", "delete":"D", "replace":"R" }
        lines = ""

        while dump.read_next_rev():
            revnr = dump.get_rev_nr()
            if revnr == self.revNr or self.revNr == -1:
                lines = ""
                for node in dump.get_nodes_iter():
                    action = actions[node.get_action()]
                    path = node.get_path()
                    if path == "" or path[0] != "/":
                        path = "/" + path
                    if node.has_copy_from():
                        fpath = node.get_copy_from_path()
                        frev = node.get_copy_from_rev()
                        if fpath == "" or fpath[0] != "/":
                            fpath = "/" + fpath
                        path += " (from %s:%d)" % ( fpath, frev )
                    lines += "   %s %s\n" % ( action, path )
                if revnr == self.revNr:
                    print lines,
                    lines = ""
                    break
        if len(lines) > 0:
            print lines,

        dump.close()
        return 0
Exemplo n.º 5
0
    def execute(self):
        """
        Executes the Edit.
        """

        # +++ catch exception and return errorcode
        srcdmp = SvnDumpFile()
        srcdmp.open(self.__in_file)

        dstdmp = None

        hasrev = srcdmp.read_next_rev()
        if hasrev:
            if not self.dry_run:
                dstdmp = SvnDumpFile()
                if srcdmp.get_rev_nr() == 0:
                    # create new dump with revision 0
                    dstdmp.create_with_rev_0(self.__out_file,
                                             srcdmp.get_uuid(),
                                             srcdmp.get_rev_date_str())
                    hasrev = srcdmp.read_next_rev()
                else:
                    # create new dump starting with the same revNr
                    # as the input dump file
                    dstdmp.create_with_rev_n(self.__out_file,
                                             srcdmp.get_uuid(),
                                             srcdmp.get_rev_nr())
            # now copy all the revisions
            while hasrev:
                self.__process_rev(srcdmp, dstdmp)
                hasrev = srcdmp.read_next_rev()
Exemplo n.º 6
0
def split_dumpfiles( inputfilename, outlist ):
    """
    Splits a dump file.

    @type inputfilename: string
    @param inputfilename: Name of the input file.
    @type outlist: list
    @param outlist: List of tuples containing start revnr, end revnr and filename.
    @rtype: int
    @return: 0 for success.
    """

    if len(outlist) == 0:
        return 0

    outlist = outlist[:]
    outlist.sort()
    parallel = False
    for i in range( 0, len(outlist)-1 ):
        if outlist[i][1] > outlist[i+1][0]:
            parallel = True
            break

    if not parallel:
        indump = SvnDumpFile()
        indump.open( inputfilename )
        index = 0
        startrev = outlist[index][0]
        endrev = outlist[index][1]
        outfile = outlist[index][2]
        outdump = None
        while indump.read_next_rev():
            revnr = indump.get_rev_nr()
            if outdump == None:
                if revnr >= startrev:
                    outdump = SvnDumpFile()
                    if revnr == 0:
                        # create new dump with revision 0
                        outdump.create_with_rev_0( outfile, indump.get_uuid(),
                                    indump.get_rev_date_str() )
                    else:
                        # create new dump starting with the
                        # same revNr as the original dump
                        outdump.create_with_rev_n( outfile, indump.get_uuid(),
                                    indump.get_rev_nr() )
            if outdump != None:
                # have an output file, copy the revision if revnr > 0
                if revnr > 0:
                    outdump.add_rev_from_dump( indump )
                if revnr >= endrev:
                    # end revision reached
                    outdump.close()
                    outdump = None
                    index += 1
                    if index >= len(outlist):
                        # done.
                        break
                    # next range
                    startrev = outlist[index][0]
                    endrev = outlist[index][1]
                    outfile = outlist[index][2]
        if outdump != None:
            outdump.close()
        indump.close()
    else:
        print "overlapping revision ranges not supported (yet)."
        return 1
    return 0
Exemplo n.º 7
0
def join_dumpfiles( inputlist, outfilename ):
    """
    Joins dump files.

    @type inputlist: list
    @param inputlist: A list containing the input filenames.
    @type outfilename: string
    @param outfilename: Name of the output dump file.
    @rtype: int
    @return: 0 for success.
    """

    outdump = None
    noutrev = 0
    lastrev = -1
    for filename in inputlist:
        print "reading %s ..." % filename
        ninrev = 0
        indump = SvnDumpFile()
        indump.open( filename )
        hasrev = indump.read_next_rev()
        if hasrev:
            if outdump == None:
                outdump = SvnDumpFile()
                if indump.get_rev_nr() == 0:
                    # create new dump with revision 0
                    outdump.create_with_rev_0( outfilename, indump.get_uuid(),
                                indump.get_rev_date_str() )
                    hasrev = indump.read_next_rev()
                else:
                    # create new dump starting with the
                    # same revNr as the original dump
                    outdump.create_with_rev_n( outfilename, indump.get_uuid(),
                                indump.get_rev_nr() )
            else:
                # check rev number
                if indump.get_rev_nr() == 0:
                    hasrev = indump.read_next_rev()
                if hasrev:
                    if (lastrev + 1) != indump.get_rev_nr():
                        print "renumbering of revisions not supported."
                        print "last rev was %d, next is %d." % ( lastrev,
                            indump.get_rev_nr() )
                        indump.close()
                        outdump.close()
                        return 1
            while hasrev:
                outdump.add_rev_from_dump( indump )
                ninrev += 1
                lastrev = indump.get_rev_nr()
                hasrev = indump.read_next_rev()
        indump.close()
        print "  copied %d revisions." % ninrev
        noutrev += ninrev
    outdump.close()
    print "wrote %d revisions, last was r%d." % ( noutrev, lastrev )
Exemplo n.º 8
0
    def execute(self, callback):
        """
        Execute the diff.

        @type callback: SvnDumpDiffCallback
        @param callback: Callback object for diffs found.
        """

        # diff started
        callback.comparing(self.__filename1, self.__filename2)

        # open files
        dump1 = SvnDumpFile()
        dump2 = SvnDumpFile()
        dump1.open(self.__filename1)
        dump2.open(self.__filename2)

        # compare uuid
        if dump1.get_uuid() != dump2.get_uuid():
            callback.rev_diff("UUID", dump1.get_uuid(), dump2.get_uuid())

        hasrev1 = dump1.read_next_rev()
        hasrev2 = dump2.read_next_rev()

        while hasrev1 and hasrev2:
            # compare rev numbers
            if dump1.get_rev_nr() != dump2.get_rev_nr():
                callback.rev_diff("RevNr", dump1.get_rev_nr(),
                                  dump2.get_rev_nr())
                # error has been reported so set both flags to false
                hasrev1 = False
                hasrev2 = False
                break

            # next revision...
            callback.next_revision(dump1.get_rev_nr(), dump2.get_rev_nr())

            # compare rev date
            if dump1.get_rev_date() != dump2.get_rev_date():
                callback.rev_diff("RevDate", str(dump1.get_rev_date()),
                                  str(dump2.get_rev_date()))
            if dump1.get_rev_date_str() != dump2.get_rev_date_str():
                callback.rev_diff("RevDateStr", dump1.get_rev_date_str(),
                                  dump2.get_rev_date_str())

            # compare rev author
            # compare rev log
            # compare rev props
            self.__compare_properties(True, dump1.get_rev_props(),
                                      dump2.get_rev_props(), callback)
            # compare nodes
            self.__compare_nodes(dump1, dump2, callback)

            # read next revision
            hasrev1 = dump1.read_next_rev()
            hasrev2 = dump2.read_next_rev()

        if hasrev1 or hasrev2:
            print "random error ;-) (different rev nr or EOF of one file)"

        # done.
        callback.compare_done()
Exemplo n.º 9
0
    def merge(self):
        """
        Executes the merge.
        """

        if len(self.__in_files) == 0:
            print("merge: no input files specified")
            return
        if len(self.__out_file) == 0:
            print("merge: no output file specified")
            return

        # open input dump files
        for inFile in self.__in_files:
            inDump = SvnDumpFile()
            inDump.open(inFile)
            inDump.read_next_rev()
            self.__in_dumps = self.__in_dumps + [inDump]
            if inDump.get_rev_date_str() < self.__out_r0_date:
                self.__out_r0_date = inDump.get_rev_date_str()

        # remove empty dumps
        dumpCount = self.__remove_empty_dumps()
        if dumpCount == 0:
            return

        # open output file
        self.outDump = SvnDumpFile()
        if self.outStartRev == 0:
            self.outDump.create_with_rev_0(self.__out_file,
                                           self.__in_dumps[0].get_uuid(), self.__out_r0_date)
        else:
            self.outDump.create_with_rev_n(self.__out_file,
                                           self.__in_dumps[0].get_uuid(), self.outStartRev)

        # skip revision 0 of all dumps
        for inDump in self.__in_dumps:
            if inDump.get_rev_nr() == 0:
                # +++ what about r0 revprops?
                inDump.read_next_rev()

        # remove empty dumps
        dumpCount = self.__remove_empty_dumps()
        if dumpCount == 0:
            self.outDump.close()
            return

        # get revision dates
        oldest = None
        oldestStr = ""
        for index in range(len(self.__in_dumps)):
            revDat = self.__in_dumps[index].get_rev_date()
            self.__in_rev_dates.append(revDat)
            if oldest is None or revDat < oldest:
                oldest = revDat
                oldestStr = self.__in_dumps[index].get_rev_date_str()

        # add additional directories
        if len(self.__out_dirs) > 0:
            self.outDump.add_rev({"svn:log": self.__out_message,
                                  "svn:author": self.__out_author,
                                  "svn:date": oldestStr})
            for dirName in self.__out_dirs:
                node = SvnDumpNode(dirName, "add", "dir")
                self.outDump.add_node(node)

        # loop over all revisions
        while dumpCount > 0:
            # find index of the oldest revision
            oldestIndex = 0
            for index in range(1, dumpCount):
                if self.__in_rev_dates[index] < self.__in_rev_dates[oldestIndex]:
                    oldestIndex = index
            # copy revision
            self.__copy_revision(oldestIndex)
            print("Revision: %-8d from r%-8d %s" % (self.outDump.get_rev_nr(),
                                                    self.__in_dumps[oldestIndex].get_rev_nr(),
                                                    self.__in_files[oldestIndex]))
            # read next revision
            srcDump = self.__in_dumps[oldestIndex]
            if srcDump.read_next_rev():
                self.__in_rev_dates[oldestIndex] = srcDump.get_rev_date()
            else:
                dumpCount = self.__remove_empty_dumps()

        # close output
        print("created %d revisions" % self.outDump.get_rev_nr())
        self.outDump.close()
Exemplo n.º 10
0
    def execute(self):
        """
        Executes the EolFix.
        """

        # +++ catch exception and return errorcode
        srcdmp = SvnDumpFile()
        srcdmp.open(self.__in_file)

        dstdmp = None

        hasrev = srcdmp.read_next_rev()
        if hasrev:
            if not self.__dry_run:
                dstdmp = SvnDumpFile()
                if srcdmp.get_rev_nr() == 0:
                    # create new dump with revision 0
                    dstdmp.create_with_rev_0(self.__out_file,
                                             srcdmp.get_uuid(),
                                             srcdmp.get_rev_date_str())
                    hasrev = srcdmp.read_next_rev()
                else:
                    # create new dump starting with the same revNr
                    # as the input dump file
                    dstdmp.create_with_rev_n(self.__out_file,
                                             srcdmp.get_uuid(),
                                             srcdmp.get_rev_nr())
            # now copy all the revisions
            while hasrev:
                print("\n\n*** r%d ***\n" % srcdmp.get_rev_nr())
                self.__process_rev(srcdmp, dstdmp)
                hasrev = srcdmp.read_next_rev()
        if self.__warning_file is not None:
            self.__warning_file.write(
                "\n\n# %d warnings\n" % self.__warning_count)
            self.__warning_file.close()
            self.__warning_file = None
            self.__warning_count = 0
Exemplo n.º 11
0
    def execute(self, dumpfilename):
        """
        Print file list of a dump file.

        @type dumpfilename: string
        @param dumpfilename: Name of the file to log.
        """

        # pass 1: search copy-from revisions
        dump = SvnDumpFile()
        dump.open(dumpfilename)
        copyfromrevs = {}
        filedict = {}

        while dump.read_next_rev():
            revnr = dump.get_rev_nr()
            if revnr > self.revNr:
                break
            for node in dump.get_nodes_iter():
                #action = actions[node.get_action()]
                action = node.get_action()
                path = node.get_path()
                if path == "" or path[0] != "/":
                    path = "/" + path
                if action == "add" and node.has_copy_from():
                    copyfromrevs[node.get_copy_from_rev()] = True
        dump.close()

        # pass 2: do the work
        dump = SvnDumpFile()
        dump.open(dumpfilename)
        filedict = {}

        prevrevnr = 0
        while dump.read_next_rev():
            revnr = dump.get_rev_nr()
            # loop over missing revisions
            prevrevnr += 1
            while prevrevnr < revnr:
                if copyfromrevs.has_key(prevrevnr):
                    copyfromrevs[prevrevnr] = filedict.keys()[:]
                prevrevnr += 1
            if revnr > self.revNr:
                break
            for node in dump.get_nodes_iter():
                action = node.get_action()
                path = node.get_path()
                if path == "" or path[0] != "/":
                    path = "/" + path
                if action == "add":
                    filedict[path] = path
                    if node.has_copy_from():
                        frompath = node.get_copy_from_path() + "/"
                        if frompath[0] != "/":
                            frompath = "/" + frompath
                        fromlen = len(frompath)
                        topath = path + "/"
                        for path in copyfromrevs[node.get_copy_from_rev()]:
                            if path.startswith(frompath):
                                newpath = topath + path[fromlen:]
                                filedict[newpath] = newpath
                elif action == "delete":
                    del filedict[path]
                    if path[-1] != "/":
                        path = path + "/"
                    for subpath in filedict.keys()[:]:
                        if subpath.startswith(path):
                            del filedict[subpath]
            if copyfromrevs.has_key(revnr):
                copyfromrevs[revnr] = filedict.keys()[:]
        dump.close()

        filelist = []
        for path in filedict:
            filelist.append(path)
        filelist.sort()
        for path in filelist:
            print path

        return 0
Exemplo n.º 12
0
    def execute( self, inputfile, outputfile ):
        """
        Fix a cvs2svn created dump file.

        @type inputfile: string
        @param inputfile: Name of the cvs2svn created dump file.
        @type outputfile: string
        @param outputfile: Name of the fixed dump file.
        """

        indump = SvnDumpFile()
        indump.open( inputfile )
        has_rev = indump.read_next_rev()
        outdump = SvnDumpFile()
        outdump.create_like( outputfile, indump )
        rc = 0
        self.__history = {}

        while has_rev and rc == 0:
            outdump.add_rev( indump.get_rev_props() )
            for node in indump.get_nodes_iter():
                msglist = self.__fix_node( indump.get_rev_nr(), node )
                if msglist != None:
                    rc = 1
                    print "Error in r%d node %s:" % \
                            ( indump.get_rev_nr(), node.get_path() )
                    for msg in msglist:
                        print "  " + msg
                    break
                outdump.add_node( node )
            has_rev = indump.read_next_rev()

        indump.close()
        return rc
Exemplo n.º 13
0
    def execute(self, inputfile, outputfile):
        """
        Fix a cvs2svn created dump file.

        @type inputfile: string
        @param inputfile: Name of the cvs2svn created dump file.
        @type outputfile: string
        @param outputfile: Name of the fixed dump file.
        """

        indump = SvnDumpFile()
        indump.open(inputfile)
        has_rev = indump.read_next_rev()
        outdump = SvnDumpFile()
        outdump.create_like(outputfile, indump)
        rc = 0
        self.__history = {}

        while has_rev and rc == 0:
            outdump.add_rev(indump.get_rev_props())
            for node in indump.get_nodes_iter():
                msglist = self.__fix_node(indump.get_rev_nr(), node)
                if msglist != None:
                    rc = 1
                    print "Error in r%d node %s:" % \
                            ( indump.get_rev_nr(), node.get_path() )
                    for msg in msglist:
                        print "  " + msg
                    break
                outdump.add_node(node)
            has_rev = indump.read_next_rev()

        indump.close()
        return rc
Exemplo n.º 14
0
    def execute(self, callback):
        """
        Execute the diff.

        @type callback: SvnDumpDiffCallback
        @param callback: Callback object for diffs found.
        """

        # diff started
        callback.comparing(self.__filename1, self.__filename2)

        # open files
        dump1 = SvnDumpFile()
        dump2 = SvnDumpFile()
        dump1.open(self.__filename1)
        dump2.open(self.__filename2)

        # compare uuid
        if dump1.get_uuid() != dump2.get_uuid():
            callback.rev_diff("UUID", dump1.get_uuid(), dump2.get_uuid())

        hasrev1 = dump1.read_next_rev()
        hasrev2 = dump2.read_next_rev()

        while hasrev1 and hasrev2:
            # compare rev numbers
            if dump1.get_rev_nr() != dump2.get_rev_nr():
                callback.rev_diff("RevNr", dump1.get_rev_nr(), dump2.get_rev_nr())
                # error has been reported so set both flags to false
                hasrev1 = False
                hasrev2 = False
                break

            # next revision...
            callback.next_revision(dump1.get_rev_nr(), dump2.get_rev_nr())

            # compare rev date
            if dump1.get_rev_date() != dump2.get_rev_date():
                callback.rev_diff("RevDate",
                                  str(dump1.get_rev_date()),
                                  str(dump2.get_rev_date()))
            if dump1.get_rev_date_str() != dump2.get_rev_date_str():
                callback.rev_diff("RevDateStr", dump1.get_rev_date_str(), dump2.get_rev_date_str())

            # compare rev author
            # compare rev log
            # compare rev props
            self.__compare_properties(True, dump1.get_rev_props(),
                                      dump2.get_rev_props(), callback)
            # compare nodes
            self.__compare_nodes(dump1, dump2, callback)

            # read next revision
            hasrev1 = dump1.read_next_rev()
            hasrev2 = dump2.read_next_rev()

        if hasrev1 or hasrev2:
            print("random error ;-) (different rev nr or EOF of one file)")

        # done.
        callback.compare_done()
Exemplo n.º 15
0
def copy_dump_file( srcfile, dstfile, transformer=None ):
    """
    Copy a dump file.

    @type srcfile: string
    @param srcfile: Source filename.
    @type dstfile: string
    @param dstfile: Destination filename.
    @type transformer: class with method transform(dump)
    @param transformer: A class to perform a transformation on each revision, or None.
    """

    # SvnDumpFile classes for reading/writing dumps
    srcdmp = SvnDumpFile()
    dstdmp = SvnDumpFile()

    # open source file
    srcdmp.open( srcfile )

    hasrev = srcdmp.read_next_rev()
    if hasrev:
        # create the dump file
        dstdmp.create_like( dstfile, srcdmp )
        # now copy all the revisions
        while hasrev:
            if transformer != None:
                transformer.transform( srcdmp )
            dstdmp.add_rev_from_dump( srcdmp )
            hasrev = srcdmp.read_next_rev()
    else:
        print "no revisions in the source dump '%s' ???" % srcfile

    # cleanup
    srcdmp.close()
    dstdmp.close()
Exemplo n.º 16
0
class SvnDumpMerge:
    """
    A class for merging svn dump files.
    """

    # handle copyfrom-rev !!!

    def __init__(self):
        """
        Initialize.
        """

        # output file name
        self.__out_file = ""
        # date for revision 0
        self.__out_r0_date = "9999-99-99T99:99:99.999999Z"
        # list additional directories
        self.__out_dirs = []
        # log message for directory creating revision
        self.__out_message = ""
        # author for the additional revision
        self.__out_author = "svndumpmerge"

        # variables used for input dump files
        # file names
        self.__in_files = []
        # path renames [ [ ( from, to ), ... ], ... ]
        self.__in_renames = []
        # path regex substitutions [ [ ( search, replace ), ... ], ... ]
        self.__in_regex_subs = []
        # mkdir excludes [ {}, ... ]
        self.__in_excludes = []
        # revision number mappings [ {}, ... ]
        self.__in_rev_nr_maps = []
        # dump files (class SvnDumpFile)
        self.__in_dumps = []
        # revision dates of the dumps
        self.__in_rev_dates = []

    def set_output_file(self, filename, startRev=0):
        """
        Sets the output file name and optional start revision.

        @type filename: string
        @param filename: Name of the output dump file.
        @type startRev: integer
        @param startRev: Start revision number, default is 0.
        """

        self.__out_file = filename
        self.outStartRev = startRev

    def add_input_file(self, filename):
        """
        Adds an input file and returns it's index.

        @type filename: string
        @param filename: Name of a input dump file.
        @rtype: integer
        @return: Index of the input file.
        """

        index = len(self.__in_files)
        self.__in_files = self.__in_files + [filename]
        self.__in_renames = self.__in_renames + [[]]
        self.__in_regex_subs = self.__in_regex_subs + [[]]
        self.__in_excludes = self.__in_excludes + [{}]
        self.__in_rev_nr_maps = self.__in_rev_nr_maps + [{}]
        return index

    def add_rename(self, index, prefixFrom, prefixTo):
        """
        Adds a path prefix reanme.

        @type index: integer
        @param index: Index of the dump file.
        @type prefixFrom: string
        @param prefixFrom: From-path prefix (directory).
        @type prefixTo: string
        @param prefixTo: To-path prefix (directory).
        """

        # make sure that prefixFrom starts and ends with a /
        if prefixFrom[0:1] == "/":
            prefixFrom = prefixFrom[1:]
        if prefixFrom[len(prefixFrom) - 1:] != "/":
            prefixFrom = prefixFrom + "/"
        # make sure that prefixTo starts and ends with a /
        if prefixTo[0:1] == "/":
            prefixTo = prefixTo[1:]
        if prefixTo[len(prefixTo) - 1:] != "/":
            prefixTo = prefixTo + "/"
        # add the rename
        self.__in_renames[index] = self.__in_renames[index] + \
                                [ (prefixFrom, prefixTo ) ]

    def add_regex_sub(self, index, reSearch, reReplace):
        """
        Adds a path prefix rename.

        @type index: integer
        @param index: Index of the dump file.
        @type reSearch: string
        @param reSearch: Search regular expression.
        @type reReplace: string
        @param reReplace: Replace regular expression.
        """

        # compile regex object
        reSearch = re.compile(reSearch)
        # add the rename
        self.__in_regex_subs[index] = self.__in_regex_subs[index] + \
                                [ (reSearch, reReplace ) ]

    def add_mkdir_exclude(self, index, dirName):
        """
        Adds a mkdir exclude.

        @type index: integer
        @param index: Index of the dump file.
        @type dirName: string
        @param dirName: Name of the directory.
        """

        # add the mkdir exclude
        self.__in_excludes[index][dirName] = None

    def add_directory(self, dirName):
        """
        Adds an additional directory ('mkdir').

        @type dirName: string
        @param dirName: Name of the directory.
        """
        if dirName[0:1] == "/":
            dirName = dirName[1:]
        if dirName[-1:] == "/":
            dirName = dirName[:-1]
        self.__out_dirs = self.__out_dirs + [dirName]

    def set_log_message(self, msg):
        """
        Set log message for additional dirs revision.

        @type msg: string
        @param msg: Log message.
        """
        self.__out_message = msg

    def merge(self):
        """
        Executes the merge.
        """

        if len(self.__in_files) == 0:
            print "merge: no input files specified"
            return
        if len(self.__out_file) == 0:
            print "merge: no output file specified"
            return

        # open input dump files
        for inFile in self.__in_files:
            inDump = SvnDumpFile()
            inDump.open(inFile)
            inDump.read_next_rev()
            self.__in_dumps = self.__in_dumps + [inDump]
            if inDump.get_rev_date_str() < self.__out_r0_date:
                self.__out_r0_date = inDump.get_rev_date_str()

        # remove empty dumps
        dumpCount = self.__remove_empty_dumps()
        if dumpCount == 0:
            return

        # open output file
        self.outDump = SvnDumpFile()
        if self.outStartRev == 0:
            self.outDump.create_with_rev_0(self.__out_file,
                                           self.__in_dumps[0].get_uuid(),
                                           self.__out_r0_date)
        else:
            self.outDump.create_with_rev_n(self.__out_file,
                                           self.__in_dumps[0].get_uuid(),
                                           self.outStartRev)

        # skip revision 0 of all dumps
        for inDump in self.__in_dumps:
            if inDump.get_rev_nr() == 0:
                # +++ what about r0 revprops?
                inDump.read_next_rev()

        # remove empty dumps
        dumpCount = self.__remove_empty_dumps()
        if dumpCount == 0:
            self.outDump.close()
            return

        # get revision dates
        oldest = None
        oldestStr = ""
        for index in range(len(self.__in_dumps)):
            revDat = self.__in_dumps[index].get_rev_date()
            self.__in_rev_dates.append(revDat)
            if oldest == None or revDat < oldest:
                oldest = revDat
                oldestStr = self.__in_dumps[index].get_rev_date_str()

        # add additional directories
        if len(self.__out_dirs) > 0:
            self.outDump.add_rev({
                "svn:log": self.__out_message,
                "svn:author": self.__out_author,
                "svn:date": oldestStr
            })
            for dirName in self.__out_dirs:
                node = SvnDumpNode(dirName, "add", "dir")
                self.outDump.add_node(node)

        # loop over all revisions
        while dumpCount > 0:
            # find index of the oldest revision
            oldestIndex = 0
            for index in range(1, dumpCount):
                if self.__in_rev_dates[index] < self.__in_rev_dates[
                        oldestIndex]:
                    oldestIndex = index
            # copy revision
            self.__copy_revision(oldestIndex)
            print "Revision: %-8d from r%-8d %s" % (
                self.outDump.get_rev_nr(),
                self.__in_dumps[oldestIndex].get_rev_nr(),
                self.__in_files[oldestIndex])
            # read next revision
            srcDump = self.__in_dumps[oldestIndex]
            if srcDump.read_next_rev():
                self.__in_rev_dates[oldestIndex] = srcDump.get_rev_date()
            else:
                dumpCount = self.__remove_empty_dumps()

        # close output
        print "created %d revisions" % self.outDump.get_rev_nr()
        self.outDump.close()

    def __copy_revision(self, dumpIndex):
        """
        Copies a revision from inDump[dumpIndex] to outDump.

        @type dumpIndex: integer
        @param dumpIndex: Index of the input dump file.
        """

        srcDump = self.__in_dumps[dumpIndex]

        # add revision and revprops
        self.outDump.add_rev(srcDump.get_rev_props())

        # add nodes
        index = 0
        nodeCount = srcDump.get_node_count()
        while index < nodeCount:
            node = srcDump.get_node(index)
            newNode = self.__change_node(dumpIndex, node)
            if newNode != None:
                self.outDump.add_node(newNode)
            index = index + 1

        # add revision info
        self.__in_rev_nr_maps[dumpIndex][srcDump.get_rev_nr()] = \
                    self.outDump.get_rev_nr()

    def __change_node(self, dumpIndex, node):
        """
        Creates a new node if the path changed, else returns the old node.

        @type dumpIndex: integer
        @param dumpIndex: Index of the input dump file.
        @type node: SvnDumpNode
        @param node: A node.
        """

        path = node.get_path()
        # mkdir exclude check
        if node.get_kind() == "dir" and node.get_action() == "add":
            if path in self.__in_excludes[dumpIndex]:
                return None
        fromPath = ""
        fromRev = 0
        if node.has_copy_from():
            fromPath = node.get_copy_from_path()
            fromRev = node.get_copy_from_rev()
        change = 0
        newPath = self.__rename_path(path, dumpIndex)
        newFromPath = fromPath
        newFromRev = fromRev
        if path != newPath:
            change = 1
        if fromRev > 0:
            newFromPath = self.__rename_path(fromPath, dumpIndex)
            if fromPath != newFromPath:
                change = 1
            newFromRev = self.__in_rev_nr_maps[dumpIndex][fromRev]
            if fromRev != newFromRev:
                change = 1

        newMergeInfo = ""
        if node.has_properties():
            properties = node.get_properties()
            if properties.has_key('svn:mergeinfo'):
                mergeInfo = properties['svn:mergeinfo']
                for line in mergeInfo.split('\n'):
                    m = re.match('^(.*):(\d+)-(\d+)', line)
                    if m != None:
                        mergePath = m.group(1)
                        mergeFrom = int(m.group(2))
                        mergeTo = int(m.group(3))
                        newMergePath = self.__rename_path(mergePath, dumpIndex)
                        newMergeFrom = self.__in_rev_nr_maps[dumpIndex][
                            mergeFrom]
                        newMergeTo = self.__in_rev_nr_maps[dumpIndex][mergeTo]
                        if len(newMergeInfo) != 0:
                            newMergeInfo = newMergeInfo + "\n"
                        newMergeInfo = newMergeInfo + newMergePath + ":" + str(
                            newMergeFrom) + "-" + str(newMergeTo)

                if mergeInfo != newMergeInfo:
                    change = 1

        if not change:
            # no change needed
            return node

        # do the rename
        newNode = SvnDumpNode(newPath, node.get_action(), node.get_kind())
        if node.has_copy_from():
            newNode.set_copy_from(newFromPath, newFromRev)
        if node.has_properties():
            newNode.set_properties(node.get_properties())
            if len(newMergeInfo) > 0:
                newNode.set_property('svn:mergeinfo', newMergeInfo)
        if node.has_text():
            newNode.set_text_node(node)
        return newNode

    def __rename_path(self, path, dumpIndex):
        """
        Applies the renames to the path and returns the new path.

        @type path: string
        @param path: A path.
        @type renames: list( ( string, string ) )
        @param renames: List of rename tuples.
        @rtype: string
        @return Renamed path.
        """

        # ensure that path does not have a leading slash
        if len(path) > 1 and path[0:1] == "/":
            path = path[1:]
        sPath = path + "/"
        for sPfx, dPfx in self.__in_renames[dumpIndex]:
            sLen = len(sPfx)
            if sPfx == "/":
                return dPfx + path
            elif sPath[:sLen] == sPfx:
                if len(path) <= len(sPfx):
                    # it's the full path
                    return dPfx[0:len(dPfx) - 1]
                else:
                    # there's a suffix
                    return dPfx + path[sLen:]
        for reSearch, sReplace in self.__in_regex_subs[dumpIndex]:
            path = reSearch.sub(sReplace, path, count=1)
        return path

    def __remove_empty_dumps(self):
        """
        Removes dump files which reached EOF and returns the count of dumps.

        @rtype: integer
        @return: Count of remaining input dump files.
        """

        index = 0
        while index < len(self.__in_dumps):
            inDump = self.__in_dumps[index]
            if inDump.has_revision():
                index = index + 1
            else:
                inDump.close()
                eidx = index + 1
                self.__in_files[index:eidx] = []
                self.__in_renames[index:eidx] = []
                self.__in_regex_subs[index:eidx] = []
                self.__in_excludes[index:eidx] = []
                self.__in_rev_nr_maps[index:eidx] = []
                self.__in_dumps[index:eidx] = []
                self.__in_rev_dates[index:eidx] = []
        return index
Exemplo n.º 17
0
    def merge(self):
        """
        Executes the merge.
        """

        if len(self.__in_files) == 0:
            print "merge: no input files specified"
            return
        if len(self.__out_file) == 0:
            print "merge: no output file specified"
            return

        # open input dump files
        for inFile in self.__in_files:
            inDump = SvnDumpFile()
            inDump.open(inFile)
            inDump.read_next_rev()
            self.__in_dumps = self.__in_dumps + [inDump]
            if inDump.get_rev_date_str() < self.__out_r0_date:
                self.__out_r0_date = inDump.get_rev_date_str()

        # remove empty dumps
        dumpCount = self.__remove_empty_dumps()
        if dumpCount == 0:
            return

        # open output file
        self.outDump = SvnDumpFile()
        if self.outStartRev == 0:
            self.outDump.create_with_rev_0(self.__out_file,
                                           self.__in_dumps[0].get_uuid(),
                                           self.__out_r0_date)
        else:
            self.outDump.create_with_rev_n(self.__out_file,
                                           self.__in_dumps[0].get_uuid(),
                                           self.outStartRev)

        # skip revision 0 of all dumps
        for inDump in self.__in_dumps:
            if inDump.get_rev_nr() == 0:
                # +++ what about r0 revprops?
                inDump.read_next_rev()

        # remove empty dumps
        dumpCount = self.__remove_empty_dumps()
        if dumpCount == 0:
            self.outDump.close()
            return

        # get revision dates
        oldest = None
        oldestStr = ""
        for index in range(len(self.__in_dumps)):
            revDat = self.__in_dumps[index].get_rev_date()
            self.__in_rev_dates.append(revDat)
            if oldest == None or revDat < oldest:
                oldest = revDat
                oldestStr = self.__in_dumps[index].get_rev_date_str()

        # add additional directories
        if len(self.__out_dirs) > 0:
            self.outDump.add_rev({
                "svn:log": self.__out_message,
                "svn:author": self.__out_author,
                "svn:date": oldestStr
            })
            for dirName in self.__out_dirs:
                node = SvnDumpNode(dirName, "add", "dir")
                self.outDump.add_node(node)

        # loop over all revisions
        while dumpCount > 0:
            # find index of the oldest revision
            oldestIndex = 0
            for index in range(1, dumpCount):
                if self.__in_rev_dates[index] < self.__in_rev_dates[
                        oldestIndex]:
                    oldestIndex = index
            # copy revision
            self.__copy_revision(oldestIndex)
            print "Revision: %-8d from r%-8d %s" % (
                self.outDump.get_rev_nr(),
                self.__in_dumps[oldestIndex].get_rev_nr(),
                self.__in_files[oldestIndex])
            # read next revision
            srcDump = self.__in_dumps[oldestIndex]
            if srcDump.read_next_rev():
                self.__in_rev_dates[oldestIndex] = srcDump.get_rev_date()
            else:
                dumpCount = self.__remove_empty_dumps()

        # close output
        print "created %d revisions" % self.outDump.get_rev_nr()
        self.outDump.close()
Exemplo n.º 18
0
def copy_dump_file( srcfile, dstfile, transformer=None ):
    """
    Copy a dump file.

    @type srcfile: string
    @param srcfile: Source filename.
    @type dstfile: string
    @param dstfile: Destination filename.
    @type transformer: class with method transform(dump)
    @param transformer: A class to perform a transformation on each revision, or None.
    """

    # SvnDumpFile classes for reading/writing dumps
    srcdmp = SvnDumpFile()
    dstdmp = SvnDumpFile()

	# Copy_from_rev casacading
    oldRevToNewRev = dict()

    # open source file
    srcdmp.open( srcfile )

    hasrev = srcdmp.read_next_rev()
    if hasrev:
        # create the dump file
        dstdmp.create_like( dstfile, srcdmp )
        # now copy all the revisions
        while hasrev:
            if transformer != None:
                transformer.transform( srcdmp )
            for node in srcdmp.get_nodes_iter():
                if node.has_copy_from():
                    if oldRevToNewRev.has_key(node.get_copy_from_rev()):
                        node.set_copy_from_rev(oldRevToNewRev[node.get_copy_from_rev()])
                    else:
                        #We have a problem, the copy from revision is missing.
						#We look for a previous revision containing the file
                        found = False
                        candidate = node.get_copy_from_rev()
                        while candidate > 0 and not found:
                            candidate = candidate - 1
                            found = oldRevToNewRev.has_key(candidate)
                        if found:
							oldRevToNewRev[node.get_copy_from_rev()] = candidate
							node.set_copy_from_rev(candidate)
            dstdmp.add_rev_from_dump( srcdmp )
            oldRevToNewRev[srcdmp.get_rev_nr()] = dstdmp.get_rev_nr()
            hasrev = srcdmp.read_next_rev()
    else:
        print "no revisions in the source dump '%s' ???" % srcfile

    # cleanup
    srcdmp.close()
    dstdmp.close()
Exemplo n.º 19
0
    def filter_dump_file(self, srcfile, dstfile ):
    
        # SvnDumpFile classes for reading/writing dumps
        srcdmp = SvnDumpFile()
        dstdmp = SvnDumpFile()
    
        # read a first time source file to find all referenced revisions (they should not be later removed)
        srcdmp.open( srcfile )
        hasrev = srcdmp.read_next_rev()
        referenced_revs = set()
        while hasrev:
            for node in srcdmp.get_nodes_iter():
                copy_from_rev = node.get_copy_from_rev()
                if copy_from_rev != 0:
                    referenced_revs.add(copy_from_rev)
            hasrev = srcdmp.read_next_rev()
        srcdmp.close()

        # start reading again source file
        srcdmp.open( srcfile )
        hasrev = srcdmp.read_next_rev()
        if hasrev:
            # create the dump file
            dstdmp.create_like( dstfile, srcdmp )
            # now copy all the revisions
            while hasrev:
                if self.verbosity > 0:
                    print "Revision-number: orig=%s, new=%s" % (srcdmp.get_rev_nr(), srcdmp.get_rev_nr()-self.skipped_revisions)
                if srcdmp.get_rev_log() == "This is an empty revision for padding." and srcdmp.get_rev_nr() not in referenced_revs:
                    if self.verbosity > 0:
                        print " * skipped padding revison (number of skipped revisions = %s)" % self.skipped_revisions
                    self.skipped_revisions += 1
                else:
                    self.transform( srcdmp )
                    self.rev_map[srcdmp.get_rev_nr()] = (srcdmp.get_rev_nr() - self.skipped_revisions)
                    dstdmp.add_rev_from_dump( srcdmp )
                hasrev = srcdmp.read_next_rev()
        else:
            print "no revisions in the source dump '%s' ???" % srcfile
    
        # cleanup
        srcdmp.close()
        dstdmp.close()
Exemplo n.º 20
0
    def execute(self, dumpfilename):
        """
        Print log of a dump file.

        @type dumpfilename: string
        @param dumpfilename: Name of the file to log.
        """

        print "\n\n" + "=" * 72
        line = "-" * 72
        print "Dumpfile: " + dumpfilename
        dump = SvnDumpFile()
        dump.open(dumpfilename)
        actions = {"add": "A", "change": "M", "delete": "D", "replace": "R"}

        while dump.read_next_rev():
            revnr = dump.get_rev_nr()
            if revnr >= self.__from_rev and revnr <= self.__to_rev:
                author = dump.get_rev_author()
                date = dump.get_rev_date_str()
                log = dump.get_rev_log()
                linecnt = len(log.split("\n"))
                lines = "%d line" % linecnt
                if linecnt > 1:
                    lines += "s"
                print line
                print "r%d | %s | %s | %s" % (revnr, author, date, lines)
                if self.__verbose:
                    print "Changed paths:"
                    for node in dump.get_nodes_iter():
                        action = actions[node.get_action()]
                        path = node.get_path()
                        if path == "" or path[0] != "/":
                            path = "/" + path
                        if node.has_copy_from():
                            fpath = node.get_copy_from_path()
                            frev = node.get_copy_from_rev()
                            if fpath == "" or fpath[0] != "/":
                                fpath = "/" + fpath
                            path += " (from %s:%d)" % (fpath, frev)
                        print "   %s %s" % (action, path)
                print "\n" + log.rstrip() + "\n"

        print line
        dump.close()
        return 0
Exemplo n.º 21
0
def split_dumpfiles(inputfilename, outlist):
    """
    Splits a dump file.

    @type inputfilename: string
    @param inputfilename: Name of the input file.
    @type outlist: list
    @param outlist: List of tuples containing start revnr, end revnr and filename.
    @rtype: int
    @return: 0 for success.
    """

    if len(outlist) == 0:
        return 0

    outlist = outlist[:]
    outlist.sort()
    parallel = False
    for i in range(0, len(outlist) - 1):
        if outlist[i][1] > outlist[i + 1][0]:
            parallel = True
            break

    if not parallel:
        indump = SvnDumpFile()
        indump.open(inputfilename)
        index = 0
        startrev = outlist[index][0]
        endrev = outlist[index][1]
        outfile = outlist[index][2]
        outdump = None
        while indump.read_next_rev():
            revnr = indump.get_rev_nr()
            if outdump == None:
                if revnr >= startrev:
                    outdump = SvnDumpFile()
                    if revnr == 0:
                        # create new dump with revision 0
                        outdump.create_with_rev_0(outfile, indump.get_uuid(),
                                                  indump.get_rev_date_str())
                    else:
                        # create new dump starting with the
                        # same revNr as the original dump
                        outdump.create_with_rev_n(outfile, indump.get_uuid(),
                                                  indump.get_rev_nr())
            if outdump != None:
                # have an output file, copy the revision if revnr > 0
                if revnr > 0:
                    outdump.add_rev_from_dump(indump)
                if revnr >= endrev:
                    # end revision reached
                    outdump.close()
                    outdump = None
                    index += 1
                    if index >= len(outlist):
                        # done.
                        break
                    # next range
                    startrev = outlist[index][0]
                    endrev = outlist[index][1]
                    outfile = outlist[index][2]
        if outdump != None:
            outdump.close()
        indump.close()
    else:
        print "overlapping revision ranges not supported (yet)."
        return 1
    return 0
Exemplo n.º 22
0
def copy_dump_file(srcfile, dstfile, transformer=None):
    """
    Copy a dump file.

    @type srcfile: string
    @param srcfile: Source filename.
    @type dstfile: string
    @param dstfile: Destination filename.
    @type transformer: class with method transform(dump)
    @param transformer: A class to perform a transformation on each revision, or None.
    """

    # SvnDumpFile classes for reading/writing dumps
    srcdmp = SvnDumpFile()
    dstdmp = SvnDumpFile()

    # Copy_from_rev casacading
    oldRevToNewRev = dict()

    # open source file
    srcdmp.open(srcfile)

    hasrev = srcdmp.read_next_rev()
    if hasrev:
        # create the dump file
        dstdmp.create_like(dstfile, srcdmp)
        # now copy all the revisions
        while hasrev:
            if transformer != None:
                transformer.transform(srcdmp)
            for node in srcdmp.get_nodes_iter():
                if node.has_copy_from():
                    if oldRevToNewRev.has_key(node.get_copy_from_rev()):
                        node.set_copy_from_rev(
                            oldRevToNewRev[node.get_copy_from_rev()])
                    else:
                        #We have a problem, the copy from revision is missing.
                        #We look for a previous revision containing the file
                        found = False
                        candidate = node.get_copy_from_rev()
                        while candidate > 0 and not found:
                            candidate = candidate - 1
                            found = oldRevToNewRev.has_key(candidate)
                        if found:
                            oldRevToNewRev[
                                node.get_copy_from_rev()] = candidate
                            node.set_copy_from_rev(candidate)
            dstdmp.add_rev_from_dump(srcdmp)
            oldRevToNewRev[srcdmp.get_rev_nr()] = dstdmp.get_rev_nr()
            hasrev = srcdmp.read_next_rev()
    else:
        print "no revisions in the source dump '%s' ???" % srcfile

    # cleanup
    srcdmp.close()
    dstdmp.close()
Exemplo n.º 23
0
def join_dumpfiles(inputlist, outfilename):
    """
    Joins dump files.

    @type inputlist: list
    @param inputlist: A list containing the input filenames.
    @type outfilename: string
    @param outfilename: Name of the output dump file.
    @rtype: int
    @return: 0 for success.
    """

    outdump = None
    noutrev = 0
    lastrev = -1
    for filename in inputlist:
        print "reading %s ..." % filename
        ninrev = 0
        indump = SvnDumpFile()
        indump.open(filename)
        hasrev = indump.read_next_rev()
        if hasrev:
            if outdump == None:
                outdump = SvnDumpFile()
                if indump.get_rev_nr() == 0:
                    # create new dump with revision 0
                    outdump.create_with_rev_0(outfilename, indump.get_uuid(),
                                              indump.get_rev_date_str())
                    hasrev = indump.read_next_rev()
                else:
                    # create new dump starting with the
                    # same revNr as the original dump
                    outdump.create_with_rev_n(outfilename, indump.get_uuid(),
                                              indump.get_rev_nr())
            else:
                # check rev number
                if indump.get_rev_nr() == 0:
                    hasrev = indump.read_next_rev()
                if hasrev:
                    if (lastrev + 1) != indump.get_rev_nr():
                        print "renumbering of revisions not supported."
                        print "last rev was %d, next is %d." % (
                            lastrev, indump.get_rev_nr())
                        indump.close()
                        outdump.close()
                        return 1
            while hasrev:
                outdump.add_rev_from_dump(indump)
                ninrev += 1
                lastrev = indump.get_rev_nr()
                hasrev = indump.read_next_rev()
        indump.close()
        print "  copied %d revisions." % ninrev
        noutrev += ninrev
    outdump.close()
    print "wrote %d revisions, last was r%d." % (noutrev, lastrev)
Exemplo n.º 24
0
    def execute( self, dumpfilename ):
        """
        Print file list of a dump file.

        @type dumpfilename: string
        @param dumpfilename: Name of the file to log.
        """

        # pass 1: search copy-from revisions
        dump = SvnDumpFile()
        dump.open( dumpfilename )
        copyfromrevs = {}
        filedict = {}

        while dump.read_next_rev():
            revnr = dump.get_rev_nr()
            if revnr > self.revNr:
                break
            for node in dump.get_nodes_iter():
                #action = actions[node.get_action()]
                action = node.get_action()
                path = node.get_path()
                if path == "" or path[0] != "/":
                    path = "/" + path
                if action == "add" and node.has_copy_from():
                    copyfromrevs[node.get_copy_from_rev()] = True
        dump.close()

        # pass 2: do the work
        dump = SvnDumpFile()
        dump.open( dumpfilename )
        filedict = {}

        prevrevnr = 0
        while dump.read_next_rev():
            revnr = dump.get_rev_nr()
            # loop over missing revisions
            prevrevnr += 1
            while prevrevnr < revnr:
                if copyfromrevs.has_key(prevrevnr):
                    copyfromrevs[prevrevnr] = filedict.keys()[:]
                prevrevnr += 1
            if revnr > self.revNr:
                break
            for node in dump.get_nodes_iter():
                action = node.get_action()
                path = node.get_path()
                if path == "" or path[0] != "/":
                    path = "/" + path
                if action == "add":
                    filedict[path] = path
                    if node.has_copy_from():
                        frompath = node.get_copy_from_path() + "/"
                        if frompath[0] != "/":
                            frompath = "/" + frompath
                        fromlen = len(frompath)
                        topath = path + "/"
                        for path in copyfromrevs[node.get_copy_from_rev()]:
                            if path.startswith( frompath ):
                                newpath = topath + path[fromlen:]
                                filedict[newpath] = newpath
                elif action == "delete":
                    del filedict[path]
                    if path[-1] != "/":
                        path = path + "/"
                    for subpath in filedict.keys()[:]:
                        if subpath.startswith( path ):
                            del filedict[subpath]
            if copyfromrevs.has_key(revnr):
                copyfromrevs[revnr] = filedict.keys()[:]
        dump.close()

        filelist = []
        for path in filedict:
            filelist.append( path )
        filelist.sort()
        for path in filelist:
            print path

        return 0
Exemplo n.º 25
0
    def execute(self):
        """
        Executes the Edit.
        """

        # +++ catch exception and return errorcode
        srcdmp = SvnDumpFile()
        srcdmp.open(self.__in_file)

        dstdmp = None

        hasrev = srcdmp.read_next_rev()
        if hasrev:
            if not self.dry_run:
                dstdmp = SvnDumpFile()
                if srcdmp.get_rev_nr() == 0:
                    # create new dump with revision 0
                    dstdmp.create_with_rev_0(self.__out_file,
                                             srcdmp.get_uuid(),
                                             srcdmp.get_rev_date_str())
                    hasrev = srcdmp.read_next_rev()
                else:
                    # create new dump starting with the same revNr
                    # as the input dump file
                    dstdmp.create_with_rev_n(self.__out_file,
                                             srcdmp.get_uuid(),
                                             srcdmp.get_rev_nr())
            # now copy all the revisions
            while hasrev:
                self.__process_rev(srcdmp, dstdmp)
                hasrev = srcdmp.read_next_rev()
Exemplo n.º 26
0
    def execute( self, dumpfilename ):
        """
        Print log of a dump file.

        @type dumpfilename: string
        @param dumpfilename: Name of the file to log.
        """

        print "\n\n" + "=" * 72
        line = "-" * 72
        print "Dumpfile: " + dumpfilename
        dump = SvnDumpFile()
        dump.open( dumpfilename )
        actions = { "add":"A", "change":"M", "delete":"D", "replace":"R" }

        while dump.read_next_rev():
            revnr = dump.get_rev_nr()
            if revnr >= self.__from_rev and revnr <= self.__to_rev:
                author = dump.get_rev_author()
                date = dump.get_rev_date_str()
                log = dump.get_rev_log()
                linecnt = len( log.split( "\n" ) )
                lines = "%d line" % linecnt
                if linecnt > 1:
                    lines += "s"
                print line
                print "r%d | %s | %s | %s" % ( revnr, author, date, lines )
                if self.__verbose:
                    print "Changed paths:"
                    for node in dump.get_nodes_iter():
                        action = actions[node.get_action()]
                        path = node.get_path()
                        if path == "" or path[0] != "/":
                            path = "/" + path
                        if node.has_copy_from():
                            fpath = node.get_copy_from_path()
                            frev = node.get_copy_from_rev()
                            if fpath == "" or fpath[0] != "/":
                                fpath = "/" + fpath
                            path += " (from %s:%d)" % ( fpath, frev )
                        print "   %s %s" % ( action, path )
                print "\n" + log.rstrip() + "\n"

        print line
        dump.close()
        return 0
Exemplo n.º 27
0
class SvnDumpMerge:
    """
    A class for merging svn dump files.
    """

    # handle copyfrom-rev !!!

    def __init__(self):
        """
        Initialize.
        """

        # output file name
        self.__out_file = ""
        # date for revision 0
        self.__out_r0_date = "9999-99-99T99:99:99.999999Z"
        # list additional directories
        self.__out_dirs = []
        # log message for directory creating revision
        self.__out_message = ""
        # author for the additional revision
        self.__out_author = "svndumpmerge"

        # variables used for input dump files
        # file names
        self.__in_files = []
        # path renames [ [ ( from, to ), ... ], ... ]
        self.__in_renames = []
        # path regex substitutions [ [ ( search, replace ), ... ], ... ]
        self.__in_regex_subs = []
        # mkdir excludes [ {}, ... ]
        self.__in_excludes = []
        # revision number mappings [ {}, ... ]
        self.__in_rev_nr_maps = []
        # dump files (class SvnDumpFile)
        self.__in_dumps = []
        # revision dates of the dumps
        self.__in_rev_dates = []

    def set_output_file(self, filename, startRev=0):
        """
        Sets the output file name and optional start revision.

        @type filename: string
        @param filename: Name of the output dump file.
        @type startRev: integer
        @param startRev: Start revision number, default is 0.
        """

        self.__out_file = filename
        self.outStartRev = startRev

    def add_input_file(self, filename):
        """
        Adds an input file and returns it's index.

        @type filename: string
        @param filename: Name of a input dump file.
        @rtype: integer
        @return: Index of the input file.
        """

        index = len(self.__in_files)
        self.__in_files = self.__in_files + [filename]
        self.__in_renames = self.__in_renames + [[]]
        self.__in_regex_subs = self.__in_regex_subs + [[]]
        self.__in_excludes = self.__in_excludes + [{}]
        self.__in_rev_nr_maps = self.__in_rev_nr_maps + [{}]
        return index

    def add_rename(self, index, prefixFrom, prefixTo):
        """
        Adds a path prefix reanme.

        @type index: integer
        @param index: Index of the dump file.
        @type prefixFrom: string
        @param prefixFrom: From-path prefix (directory).
        @type prefixTo: string
        @param prefixTo: To-path prefix (directory).
        """

        # make sure that prefixFrom starts and ends with a /
        if prefixFrom[0:1] == "/":
            prefixFrom = prefixFrom[1:]
        if prefixFrom[len(prefixFrom) - 1:] != "/":
            prefixFrom = prefixFrom + "/"
        # make sure that prefixTo starts and ends with a /
        if prefixTo[0:1] == "/":
            prefixTo = prefixTo[1:]
        if prefixTo[len(prefixTo) - 1:] != "/":
            prefixTo = prefixTo + "/"
        # add the rename
        self.__in_renames[index] = self.__in_renames[index] + \
                                   [(prefixFrom, prefixTo)]

    def add_regex_sub(self, index, reSearch, reReplace):
        """
        Adds a path prefix rename.

        @type index: integer
        @param index: Index of the dump file.
        @type reSearch: string
        @param reSearch: Search regular expression.
        @type reReplace: string
        @param reReplace: Replace regular expression.
        """

        # compile regex object
        reSearch = re.compile(reSearch)
        # add the rename
        self.__in_regex_subs[index] = self.__in_regex_subs[index] + \
                                      [(reSearch, reReplace)]

    def add_mkdir_exclude(self, index, dirName):
        """
        Adds a mkdir exclude.

        @type index: integer
        @param index: Index of the dump file.
        @type dirName: string
        @param dirName: Name of the directory.
        """

        # add the mkdir exclude
        self.__in_excludes[index][dirName] = None

    def add_directory(self, dirName):
        """
        Adds an additional directory ('mkdir').

        @type dirName: string
        @param dirName: Name of the directory.
        """
        if dirName[0:1] == "/":
            dirName = dirName[1:]
        if dirName[-1:] == "/":
            dirName = dirName[:-1]
        self.__out_dirs = self.__out_dirs + [dirName]

    def set_log_message(self, msg):
        """
        Set log message for additional dirs revision.

        @type msg: string
        @param msg: Log message.
        """
        self.__out_message = msg

    def merge(self):
        """
        Executes the merge.
        """

        if len(self.__in_files) == 0:
            print("merge: no input files specified")
            return
        if len(self.__out_file) == 0:
            print("merge: no output file specified")
            return

        # open input dump files
        for inFile in self.__in_files:
            inDump = SvnDumpFile()
            inDump.open(inFile)
            inDump.read_next_rev()
            self.__in_dumps = self.__in_dumps + [inDump]
            if inDump.get_rev_date_str() < self.__out_r0_date:
                self.__out_r0_date = inDump.get_rev_date_str()

        # remove empty dumps
        dumpCount = self.__remove_empty_dumps()
        if dumpCount == 0:
            return

        # open output file
        self.outDump = SvnDumpFile()
        if self.outStartRev == 0:
            self.outDump.create_with_rev_0(self.__out_file,
                                           self.__in_dumps[0].get_uuid(), self.__out_r0_date)
        else:
            self.outDump.create_with_rev_n(self.__out_file,
                                           self.__in_dumps[0].get_uuid(), self.outStartRev)

        # skip revision 0 of all dumps
        for inDump in self.__in_dumps:
            if inDump.get_rev_nr() == 0:
                # +++ what about r0 revprops?
                inDump.read_next_rev()

        # remove empty dumps
        dumpCount = self.__remove_empty_dumps()
        if dumpCount == 0:
            self.outDump.close()
            return

        # get revision dates
        oldest = None
        oldestStr = ""
        for index in range(len(self.__in_dumps)):
            revDat = self.__in_dumps[index].get_rev_date()
            self.__in_rev_dates.append(revDat)
            if oldest is None or revDat < oldest:
                oldest = revDat
                oldestStr = self.__in_dumps[index].get_rev_date_str()

        # add additional directories
        if len(self.__out_dirs) > 0:
            self.outDump.add_rev({"svn:log": self.__out_message,
                                  "svn:author": self.__out_author,
                                  "svn:date": oldestStr})
            for dirName in self.__out_dirs:
                node = SvnDumpNode(dirName, "add", "dir")
                self.outDump.add_node(node)

        # loop over all revisions
        while dumpCount > 0:
            # find index of the oldest revision
            oldestIndex = 0
            for index in range(1, dumpCount):
                if self.__in_rev_dates[index] < self.__in_rev_dates[oldestIndex]:
                    oldestIndex = index
            # copy revision
            self.__copy_revision(oldestIndex)
            print("Revision: %-8d from r%-8d %s" % (self.outDump.get_rev_nr(),
                                                    self.__in_dumps[oldestIndex].get_rev_nr(),
                                                    self.__in_files[oldestIndex]))
            # read next revision
            srcDump = self.__in_dumps[oldestIndex]
            if srcDump.read_next_rev():
                self.__in_rev_dates[oldestIndex] = srcDump.get_rev_date()
            else:
                dumpCount = self.__remove_empty_dumps()

        # close output
        print("created %d revisions" % self.outDump.get_rev_nr())
        self.outDump.close()

    def __copy_revision(self, dumpIndex):
        """
        Copies a revision from inDump[dumpIndex] to outDump.

        @type dumpIndex: integer
        @param dumpIndex: Index of the input dump file.
        """

        srcDump = self.__in_dumps[dumpIndex]

        # add revision and revprops
        self.outDump.add_rev(srcDump.get_rev_props())

        # add nodes
        index = 0
        nodeCount = srcDump.get_node_count()
        while index < nodeCount:
            node = srcDump.get_node(index)
            newNode = self.__change_node(dumpIndex, node)
            if newNode is not None:
                self.outDump.add_node(newNode)
            index = index + 1

        # add revision info
        self.__in_rev_nr_maps[dumpIndex][srcDump.get_rev_nr()] = \
            self.outDump.get_rev_nr()

    def __change_node(self, dumpIndex, node):
        """
        Creates a new node if the path changed, else returns the old node.

        @type dumpIndex: integer
        @param dumpIndex: Index of the input dump file.
        @type node: SvnDumpNode
        @param node: A node.
        """

        path = node.get_path()
        # mkdir exclude check
        if node.get_kind() == "dir" and node.get_action() == "add":
            if path in self.__in_excludes[dumpIndex]:
                return None
        fromPath = ""
        fromRev = 0
        if node.has_copy_from():
            fromPath = node.get_copy_from_path()
            fromRev = node.get_copy_from_rev()
        change = 0
        newPath = self.__rename_path(path, dumpIndex)
        newFromPath = fromPath
        newFromRev = fromRev
        if path != newPath:
            change = 1
        if fromRev > 0:
            newFromPath = self.__rename_path(fromPath, dumpIndex)
            if fromPath != newFromPath:
                change = 1
            newFromRev = self.__in_rev_nr_maps[dumpIndex][fromRev]
            if fromRev != newFromRev:
                change = 1

        newMergeInfo = ""
        if node.has_properties():
            properties = node.get_properties()
            if properties.has_key('svn:mergeinfo'):
                mergeInfo = properties['svn:mergeinfo']
                for line in mergeInfo.split('\n'):
                    m = re.match('^(.*):(.*)', line)
                    if m is not None:
                        mergePath = m.group(1)
                        revPart = m.group(2)
                        newMergePath = self.__rename_path(mergePath, dumpIndex)
                        if not newMergePath.startswith("/"):
                            newMergePath = "/" + newMergePath
                        if len(newMergeInfo) != 0:
                            newMergeInfo = newMergeInfo + "\n"
                        newMergeInfo = newMergeInfo + newMergePath + ":"
                        revSep = ""
                        for rm in re.finditer('(\d+)(?:-(\d+))?,?', revPart):
                            mergeFrom = int(rm.group(1))
                            newMergeFrom = self.__in_rev_nr_maps[dumpIndex][mergeFrom]
                            newMergeInfo = newMergeInfo + revSep + str(newMergeFrom)
                            revSep = ","
                            if rm.group(2) is not None:
                                mergeTo = int(rm.group(2))
                                newMergeTo = self.__in_rev_nr_maps[dumpIndex][mergeTo]
                                newMergeInfo = newMergeInfo + "-" + str(newMergeTo)

                if mergeInfo != newMergeInfo:
                    change = 1

        if not change:
            # no change needed
            return node

        # do the rename
        newNode = SvnDumpNode(newPath, node.get_action(), node.get_kind())
        if node.has_copy_from():
            newNode.set_copy_from(newFromPath, newFromRev)
        if node.has_properties():
            newNode.set_properties(node.get_properties())
            if len(newMergeInfo) > 0:
                newNode.set_property('svn:mergeinfo', newMergeInfo)
        if node.has_text():
            newNode.set_text_node(node)
        return newNode

    def __rename_path(self, path, dumpIndex):
        """
        Applies the renames to the path and returns the new path.

        @type path: string
        @param path: A path.
        @type renames: list( ( string, string ) )
        @param renames: List of rename tuples.
        @rtype: string
        @return Renamed path.
        """

        # ensure that path does not have a leading slash
        if len(path) > 1 and path[0:1] == "/":
            path = path[1:]
        sPath = path + "/"
        for sPfx, dPfx in self.__in_renames[dumpIndex]:
            sLen = len(sPfx)
            if sPfx == "/":
                return dPfx + path
            elif sPath[:sLen] == sPfx:
                if len(path) <= len(sPfx):
                    # it's the full path
                    return dPfx[0:len(dPfx) - 1]
                else:
                    # there's a suffix
                    return dPfx + path[sLen:]
        for reSearch, sReplace in self.__in_regex_subs[dumpIndex]:
            path = reSearch.sub(sReplace, path, count=1)
        return path

    def __remove_empty_dumps(self):
        """
        Removes dump files which reached EOF and returns the count of dumps.

        @rtype: integer
        @return: Count of remaining input dump files.
        """

        index = 0
        while index < len(self.__in_dumps):
            inDump = self.__in_dumps[index]
            if inDump.has_revision():
                index = index + 1
            else:
                inDump.close()
                eidx = index + 1
                self.__in_files[index:eidx] = []
                self.__in_renames[index:eidx] = []
                self.__in_regex_subs[index:eidx] = []
                self.__in_excludes[index:eidx] = []
                self.__in_rev_nr_maps[index:eidx] = []
                self.__in_dumps[index:eidx] = []
                self.__in_rev_dates[index:eidx] = []
        return index
Exemplo n.º 28
0
def copy_dump_file(srcfile, dstfile, transformer=None):
    """
    Copy a dump file.

    @type srcfile: string
    @param srcfile: Source filename.
    @type dstfile: string
    @param dstfile: Destination filename.
    @type transformer: class with method transform(dump)
    @param transformer: A class to perform a transformation on each revision, or None.
    """

    # SvnDumpFile classes for reading/writing dumps
    srcdmp = SvnDumpFile()
    dstdmp = SvnDumpFile()

    # open source file
    srcdmp.open(srcfile)

    hasrev = srcdmp.read_next_rev()
    if hasrev:
        # create the dump file
        dstdmp.create_like(dstfile, srcdmp)
        # now copy all the revisions
        while hasrev:
            if transformer != None:
                transformer.transform(srcdmp)
            dstdmp.add_rev_from_dump(srcdmp)
            hasrev = srcdmp.read_next_rev()
    else:
        print "no revisions in the source dump '%s' ???" % srcfile

    # cleanup
    srcdmp.close()
    dstdmp.close()