# 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)