thirdparty/vcs-load-dirs/vcs_support/vcs_interact.py
author Mario Ferraro <fadinlight@gmail.com>
Sun, 15 Nov 2009 22:12:20 +0100
changeset 3093 d1be59b6b627
parent 2311 e8262ca32109
permissions -rw-r--r--
GMaps related JS changed to use new google namespace. Google is going to change permanently in the future the way to load its services, so better stay safe. Also this commit shows uses of the new melange.js module. Fixes Issue 634.

# Copyright (C) 2003-2007 John Goerzen
# <jgoerzen@complete.org>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import sys, os
import util
from commandver import isdarcs
from tempfile import mkdtemp

class interaction:
    def __init__(self, wcobj, importdir, docommit, log = '', verbose = 0,
                 summary = None):
        self.wcobj = wcobj
        self.log = log
        self.docommit = docommit
        self.verb = verbose
        self.summary = summary

        if os.path.isdir(importdir):
            self.importdir = os.path.abspath(importdir)
            self.importfile = None
            self.tmpdir = None

        else:                           # Not a dir, try to unpack an archive.
            self.importfile = os.path.abspath(importdir)
            # mkdtemp returns an absolute path
            self.importdir = mkdtemp("-vcs-load-dirs", ",,unpack-", "..")
            self.tmpdir = self.importdir

            try:
                if self.verb:
                    print "Unpacking archive..."

                if self.importfile.endswith(".tar.gz"):
                    util.chdircmd(self.importdir, util.safeexec, "tar",
                                  ["-zxf", self.importfile])

                elif self.importfile.endswith(".tar.bz2"):
                    util.chdircmd(self.importdir, util.safeexec, "tar",
                                  ["-jxf", self.importfile])
                elif self.importfile.endswith(".zip"):
                    util.chdircmd(self.importdir, util.safeexec, "unzip",
                                  [self.importfile])
                else:
                    raise IOError, "Unknown archive file type"

                # Many tarballs expand into just one single directory.
                # Check to see if that's the case.

                dents = os.listdir(self.importdir)
                if len(dents) == 1 and os.path.isdir(self.importdir + "/" +
                                                     dents[0]):
                    self.importdir = self.importdir + "/" + dents[0]
            except:
                self.cleanup()
                raise

    def cleanup(self):
        if not (self.tmpdir is None):
            util.safeexec("rm", ["-rf", self.tmpdir])
            self.tmpdir = None

    def updateimportfiles(self):
        if self.verb:
            print "Scanning upstream tree..."
        self.importfiles = util.maketree(self.importdir)

    def updatewcfiles(self):
        if self.verb:
            print "Scanning working copy tree..."
        self.wcfiles = self.wcobj.gettree()

    def update(self):
        self.updatewcfiles()
        self.updatechangedfiles()

    def updatechangedfiles(self):
        if self.verb:
            print "Calculating changes..."
        wcfilehash = {}
        for x in self.wcfiles:
            wcfilehash[x] = 1
        importfilehash = {}
        for x in self.importfiles:
            importfilehash[x] = 1
        
        self.addedfiles = [x for x in self.importfiles if not wcfilehash.has_key(x)]
        self.deletedfiles = [x for x in self.wcfiles if not importfilehash.has_key(x)]
        

    def main(self):
        def readloop():
            for command in sys.stdin.readline().strip().split(','):
                command = command.strip()
                if command == 'q':
                    return 0
                if command == 'r':
                    return 1
                src, dest = command.split(' ')
                src = int(src, 16)
                dest = int(dest, 16)
                self.mv(self.deletedfiles[src], self.addedfiles[dest])
            return 1

        self.updateimportfiles()
        needsupdate = 1
        
        while 1:
            self.update()
            if self.wcobj.fsonly:
                # Don't show this interface if we're not talking to the VCS
                break
            if not (len(self.addedfiles) and len(self.deletedfiles)):
                # Just ran update; don't do it again.
                needsupdate = 0
                break

            counter = 0
            print "%3s %-35s %3s %-35s" % ('Num', 'Source Files', 'Num',
                                             'Destination Files',)
            print "%s %s %s %s" % ("-" * 3, "-" * 35, "-" * 3, "-" * 35)
            while counter < max(len(self.addedfiles), len(self.deletedfiles)):
                addfile = ''
                delfile = ''
                if counter < len(self.addedfiles):
                    addfile = self.addedfiles[counter]
                if counter < len(self.deletedfiles):
                    delfile = self.deletedfiles[counter]
                print "%3x %-35s %3x %-35s" % (counter, delfile, counter, addfile)
                counter += 1
            print "Syntax: src dest [,src dest [,...]] to move, q to accept, r to redraw:"
            sys.stdout.write("Command: ")
            sys.stdout.flush()
            try:
                if not readloop():
                    break
            except ValueError:
                print "Error handling input; please try again."
            except IndexError:
                print "Error handling input; please try again."

        self.catchup(needsupdate)
        
    def catchup(self, needsupdate = 1):
        if self.verb:
            print " *** Processing changes."
        if needsupdate:
            self.update()
        if self.verb:
            print "Deleting %d files" % len(self.deletedfiles)
        if isdarcs():
            for file in util.sorttree(self.deletedfiles, filesfirst = True):
                self.delfile(file)
        else:
            for file in self.deletedfiles:
                self.delfile(file)

        if self.verb:
            print "Copying upstream directory to working copy..."
        util.copyfrom(self.importdir, self.wcobj.wcpath)

        if self.verb:
            print "Adding %d files" % len(self.addedfiles)
        self.addedfiles.sort() # Make sure top-level dirs added before files
        for file in self.addedfiles:
            self.addfile(file)
        self.writelog()
        if self.docommit:
            self.wcobj.commit()

    def writelog(self):
        logtext = ""
        if not (self.importfile is None):
            importname = self.importfile
        else:
            importname = self.importdir
            
        if self.summary:
            summary = self.summary
        else:
            summary = "Imported %s" % os.path.basename(importname)
        logtext += "Imported %s\ninto %s\n\n" % \
                   (os.path.basename(importname),
                   self.wcobj.gettreeversion())
        logtext += self.log
        self.wcobj.makelog(summary, logtext)
        

    def addfile(self, file):
        self.wcobj.addtag(file)

    def delfile(self, file):
        self.wcobj.deltag(file)
        self.wcobj.delfile(file)
    
        
    def mv(self, src, dest):
        print "%s -> %s" % (src, dest)
        self.wcobj.movefile(src, dest)
        self.wcobj.movetag(src, dest)