Package translate :: Package storage :: Package versioncontrol :: Module cvs

[hide private]
[frames] | no frames]

# Source Code for Module translate.storage.versioncontrol.cvs

      1  #!/usr/bin/env python
      2  # -*- coding: utf-8 -*-
      3  #
      4  # Copyright 2004-2007 Zuza Software Foundation
      5  #
      6  # This file is part of translate.
      7  #
      8  # translate is free software; you can redistribute it and/or modify
      9  # it under the terms of the GNU General Public License as published by
     10  # the Free Software Foundation; either version 2 of the License, or
     11  # (at your option) any later version.
     12  #
     13  # translate is distributed in the hope that it will be useful,
     14  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  # GNU General Public License for more details.
     17  #
     18  # You should have received a copy of the GNU General Public License
     19  # along with translate; if not, write to the Free Software
     20  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     21
     22  import os
     23  from translate.storage.versioncontrol import GenericRevisionControlSystem
     24  from translate.storage.versioncontrol import run_command
     25
     26
     27 -def is_available():
     28      """check if cvs is installed"""
     29      exitcode, output, error = run_command(["cvs", "--version"])
     30      return exitcode == 0
     31
     32
     33 -class cvs(GenericRevisionControlSystem):
     34      """Class to manage items under revision control of CVS."""
     35
     36      RCS_METADIR = "CVS"
     37      SCAN_PARENTS = False
     38
     39 -    def _readfile(self, cvsroot, path, revision=None):
     40          """
     41          Read a single file from the CVS repository without checking out a full
     42          working directory.
     43
     44          @param cvsroot: the CVSROOT for the repository
     45          @param path: path to the file relative to cvs root
     46          @param revision: revision or tag to get (retrieves from HEAD if None)
     47          """
     48          command = ["cvs", "-d", cvsroot, "-Q", "co", "-p"]
     49          if revision:
     50              command.extend(["-r", revision])
     51          # the path is the last argument
     52          command.append(path)
     53          exitcode, output, error = run_command(command)
     54          if exitcode != 0:
     55              raise IOError("[CVS] Could not read '%s' from '%s': %s / %s" % \
     56                      (path, cvsroot, output, error))
     57          return output
     58
     59 -    def getcleanfile(self, revision=None):
     60          """Get the content of the file for the given revision"""
     61          parentdir = os.path.dirname(self.location_abs)
     62          cvsdir = os.path.join(parentdir, "CVS")
     63          cvsroot = open(os.path.join(cvsdir, "Root"), "r").read().strip()
     64          cvspath = open(os.path.join(cvsdir, "Repository"), "r").read().strip()
     65          cvsfilename = os.path.join(cvspath, os.path.basename(self.location_abs))
     66          if revision is None:
     67              cvsentries = open(os.path.join(cvsdir, "Entries"), "r").readlines()
     68              revision = self._getcvstag(cvsentries)
     69          if revision == "BASE":
     70              cvsentries = open(os.path.join(cvsdir, "Entries"), "r").readlines()
     71              revision = self._getcvsrevision(cvsentries)
     72          return self._readfile(cvsroot, cvsfilename, revision)
     73
     74 -    def update(self, revision=None):
     75          """Does a clean update of the given path"""
     76          working_dir = os.path.dirname(self.location_abs)
     77          filename = self.location_abs
     78          filename_backup = filename + os.path.extsep + "bak"
     79          # rename the file to be updated
     80          try:
     81              os.rename(filename, filename_backup)
     82          except OSError, error:
     83              raise IOError("[CVS] could not move the file '%s' to '%s': %s" % \
     84                      (filename, filename_backup, error))
     85          command = ["cvs", "-Q", "update", "-C"]
     86          if revision:
     87              command.extend(["-r", revision])
     88          # the filename is the last argument
     89          command.append(os.path.basename(filename))
     90          # run the command within the given working_dir
     91          exitcode, output, error = run_command(command, working_dir)
     92          # restore backup in case of an error - remove backup for success
     93          try:
     94              if exitcode != 0:
     95                  os.rename(filename_backup, filename)
     96              else:
     97                  os.remove(filename_backup)
     98          except OSError:
     99              pass
    100          # raise an error or return successfully - depending on the CVS command
    101          if exitcode != 0:
    102              raise IOError("[CVS] Error running CVS command '%s': %s" \
    103                      % (command, error))
    104          else:
    105              return output
    106
    107 -    def commit(self, message=None, author=None):
    108          """Commits the file and supplies the given commit message if present
    109
    110          the 'author' parameter is not suitable for CVS, thus it is ignored
    111          """
    112          working_dir = os.path.dirname(self.location_abs)
    113          filename = os.path.basename(self.location_abs)
    114          command = ["cvs", "-Q", "commit"]
    115          if message:
    116              command.extend(["-m", message])
    117          # the filename is the last argument
    118          command.append(filename)
    119          exitcode, output, error = run_command(command, working_dir)
    120          # raise an error or return successfully - depending on the CVS command
    121          if exitcode != 0:
    122              raise IOError("[CVS] Error running CVS command '%s': %s" \
    123                      % (command, error))
    124          else:
    125              return output
    126
    127 -    def _getcvsrevision(self, cvsentries):
    128          """returns the revision number the file was checked out with by looking
    129          in the lines of cvsentries
    130          """
    131          filename = os.path.basename(self.location_abs)
    132          for cvsentry in cvsentries:
    133              # an entries line looks like the following:
    134              #  /README.TXT/1.19/Sun Dec 16 06:00:12 2001//
    135              cvsentryparts = cvsentry.split("/")
    136              if len(cvsentryparts) < 6:
    137                  continue
    138              if os.path.normcase(cvsentryparts[1]) == os.path.normcase(filename):
    139                  return cvsentryparts[2].strip()
    140          return None
    141
    142 -    def _getcvstag(self, cvsentries):
    143          """Returns the sticky tag the file was checked out with by looking in
    144          the lines of cvsentries.
    145          """
    146          filename = os.path.basename(self.location_abs)
    147          for cvsentry in cvsentries:
    148              # an entries line looks like the following:
    149              #  /README.TXT/1.19/Sun Dec 16 06:00:12 2001//
    150              cvsentryparts = cvsentry.split("/")
    151              if len(cvsentryparts) < 6:
    152                  continue
    153              if os.path.normcase(cvsentryparts[1]) == os.path.normcase(filename):
    154                  if cvsentryparts[5].startswith("T"):
    155                      return cvsentryparts[5][1:].strip()
    156          return None
    157