Ingresar:

Python :: Blog :: [svn2hg.py] Convertir repositorio subversion a mercurial

January 30, 2007

El siguiente script permite tener sincronizado un repositorio mercurial con un subversion. Solo es, como se diría "one-way".

  #!/usr/bin/env python # -*- coding: utf-8 -*- # $Id$ # # (c) 2007 - Rolando Espinoza La Fuente <darkrho@gmail.com> # Distributed under the BSD License # Use at your own risk! # # This script make a mercurial repository from a svn one. # Keeping revision history with authors and dates. # Just convert one-way, svn to hg. If you want two-way conversion checkout tailor. # # # Requirements: #   - Mercurial of course ;) #   - pysvn subversion bindings #     Ubuntu users: apt-get install python-svn # # Based on: #   <a href="http://www.selenic.com/mercurial/wiki/index.cgi/SubversionToMercurialSync">http://www.selenic.com/mercurial/wiki/index.cgi/SubversionToMe</a> # # (use backups) # Usage: svn2hg.py svnrepo # # Tested on Ubuntu Edgy against small repositories (<20Mb) # TODO: Need more testing   import sys, os   # really don't need cPickle # TODO: take out cPickle import cPickle   import pysvn # svn functions import mercurial.commands # hg functions   class svn2hg:       def __init__(self, args):         if len(args) != 1:            sys.stderr.write("[*] Error: have to provide one argumentn")            sys.exit(-1)           if not os.path.isdir(args[0]):            sys.stderr.write("[*] Error: argument must be a directoryn")            sys.exit(-1)           else:            self.path = os.path.realpath(args[0]) + os.path.sep            self.statefile = self.path + '.svn2hg_state'       def _pysvnrev(self, rev):         return pysvn.Revision(pysvn.opt_revision_kind.number, rev)       def savestate(self):         #TODO: try/catch errors         if self.currev:            try:                 cPickle.dump(self.currev, open(self.statefile,'wb+'))            except:                 pass             def loadstate(self):         #TODO: try/catch errors         if os.path.exists(self.statefile):            try:                 self.currev = cPickle.load(open(self.statefile))            except:                 self.currev = None                 pass         else:            self.currev = None       def builddate(self, timestamp):         from datetime import datetime         import time           format = '%Y-%m-%d %H:%M'         date = datetime.fromtimestamp(timestamp)         return time.strftime(format, date.timetuple())       def check_hg(self):         hgdir = self.path + '.hg'         hgignore = self.path + '.hgignore'           if not os.path.exists(hgdir):            self.hg.dispatch(['init',self.path])            ignoreme = ".hgignoren.svnn" + os.path.basename(self.statefile) + 'n'            open(hgignore, 'w').writelines(ignoreme)           elif not os.path.isdir(hgdir):            sys.stderr.write("[*] Error: unknown .hg directoryn")            sys.exit(-1)       def check_svn(self):         svndir = self.path + '.svn'           if not os.path.exists(svndir) or not os.path.isdir(svndir):            sys.stderr.write("[*] Error: unknown .svn directoryn")            sys.exit(-1)             def run(self):         self.loadstate()           self.svn = pysvn.Client()         self.hg = mercurial.commands           self.check_hg()         self.check_svn()           # why?         # get local repo info to get the url         self.info = self.svn.info2(self.path, recurse=False)[0][1]         #self.url = self.info['repos_root_URL']         self.url = self.info['URL']           ## Get current revisions...         #print '+ Updating svn repos... '         #self.newrev = self.svn.update(self.path)[0]         #self.newrev = self.newrev.number         #print 'donen'           # Getting last revision         print '[+] Getting last revision number from remote repo... '         self.remoteinfo = self.svn.info2(self.url, recurse=False)[0][1]         self.newrev = self.remoteinfo['last_changed_rev'].number                   # newer revision?         if not self.currev == self.newrev:              if not self.currev:                 self.currev = 0              print '[+] Getting remote changelog from r%s up to r%s)... ' % (self.currev, self.newrev)            svnlog = self.svn.log(self.url, self._pysvnrev(self.newrev), self._pysvnrev(self.currev))              # reverse to process from old to new            svnlog.reverse()              # fix, hg needs to 'be' inside the repo            os.chdir(self.path)              # cset dict            #   - author ""            #   - changed_paths []            #   - date timestamp            #   - message ""            #   - revision _pysvnrev              # process one by one            for cset in svnlog:                 # update to rev                 localrev = self.svn.update(self.path, revision=cset['revision'])[0]                   if not cset['message']:                     # dirty hack to prevent rollback on empty svn commit message                     cset['message'] = cset['author']                   # commit changes to hg                 # mantain the same author, message and date of the changeset                 print '[+] Process revision r%s ...' % (localrev.number)                 self.hg.dispatch(['commit', '-A', '-m', cset['message'],                                             '-u', cset['author'],                                             '-d', self.builddate(cset['date'])])              # save newrev as currev            self.currev = self.newrev           else:            print '[-] Nothing to do'           # save currev to a file for further updates         self.savestate()   if __name__ == '__main__':     main = svn2hg(sys.argv[1:])     sys.exit(main.run())     

 Download svn2hg.py

Palabras clave: convert svn to hg, mercuial to subversion, mercurial, python, script, subversion, svn2hg, tailor

Enviado por Rho @ Python



Comentarios

  1. Hola

    Invitado on Tuesday, 30 January 2007, 16:55 BOT # |

Debes iniciar sesión para enviar un comentario.