svn问题处理

来源:互联网 发布:java得到文件路径 编辑:程序博客网 时间:2024/06/05 05:37

1.问题:svn客户端更新代码报错“svn: This client is too old to work with……”
原因:svn之间的版本差异造成。当我们已经用1.4版本的svn checkout一份work copy后,但某天我们尝试用高版本1.5svn更新,等再切换成1.4svn更新代码时就会出现此错误。具体请见”http://subversion.apache.org/faq.html#working-copy-format-change”
解决方法:除了客户端升级之外,我们还可以通过对work copy进行降级处理。如下:

[root@test ~]# svn up /test/websvn: This client is too old to work with working copy ‘/test/web’. You needto get a newer Subversion client, or to downgrade this working copy.See http://subversion.tigris.org/faq.html#working-copy-format-changefor details.

(1)下载脚本change-svn-wc-format.py

[root@test ~]# wget http://svn.apache.org/repos/asf/subversion/trunk/tools/client-side/change-svn-wc-format.py[root@test ~]# python change-svn-wc-format.py --helpusage: change-svn-wc-format.py WC_PATH SVN_VERSION [--verbose] [--force] [--skip-unknown-format]       change-svn-wc-format.py --helpChange the format of a Subversion working copy to that of SVN_VERSION.  --skip-unknown-format    : skip directories with unknown working copy                             format and continue the update

其中:
WC_PATH 表示你的work copy
SVN_VERSION 表示你当前使用的svn客户端版本号,如版本为1.4.2,就写成1.4
(2)执行命令

[root@test ~]# python change-svn-wc-format.py /web/app.cityrebank.com 1.4 --skip-unknown-formatConverted WC at '/test/web' into format 8 for Subversion 1.4

(3)svn up 再次更新,成功

脚本代码如下:

[root@test ~]# vim change-svn-wc-format.py#!/usr/bin/env python## change-svn-wc-format.py: Change the format of a Subversion working copy.## ====================================================================#    Licensed to the Apache Software Foundation (ASF) under one#    or more contributor license agreements.  See the NOTICE file#    distributed with this work for additional information#    regarding copyright ownership.  The ASF licenses this file#    to you under the Apache License, Version 2.0 (the#    "License"); you may not use this file except in compliance#    with the License.  You may obtain a copy of the License at##      http://www.apache.org/licenses/LICENSE-2.0##    Unless required by applicable law or agreed to in writing,#    software distributed under the License is distributed on an#    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY#    KIND, either express or implied.  See the License for the#    specific language governing permissions and limitations#    under the License.# ====================================================================import sysimport osimport getopttry:  my_getopt = getopt.gnu_getoptexcept AttributeError:  my_getopt = getopt.getopt### The entries file parser in subversion/tests/cmdline/svntest/entry.py### handles the XML-based WC entries file format used by Subversion### 1.3 and lower.  It could be rolled into this script.LATEST_FORMATS = { "1.4" : 8,                   "1.5" : 9,                   "1.6" : 10,                   # Do NOT add format 11 here.  See comment in must_retain_fields                   # for why.                 }def usage_and_exit(error_msg=None):  """Write usage information and exit.  If ERROR_MSG is provide, that  error message is printed first (to stderr), the usage info goes to  stderr, and the script exits with a non-zero status.  Otherwise,  usage info goes to stdout and the script exits with a zero status."""  progname = os.path.basename(sys.argv[0])  stream = error_msg and sys.stderr or sys.stdout  if error_msg:    stream.write("ERROR: %s\n\n" % error_msg)  stream.write("""\usage: %s WC_PATH SVN_VERSION [--verbose] [--force] [--skip-unknown-format]       %s --helpChange the format of a Subversion working copy to that of SVN_VERSION.  --skip-unknown-format    : skip directories with unknown working copy                             format and continue the update""" % (progname, progname))  stream.flush()  sys.exit(error_msg and 1 or 0)def get_adm_dir():  """Return the name of Subversion's administrative directory,  adjusted for the SVN_ASP_DOT_NET_HACK environment variable.  See  <http://svn.apache.org/repos/asf/subversion/trunk/notes/asp-dot-net-hack.txt>  for details."""  return "SVN_ASP_DOT_NET_HACK" in os.environ and "_svn" or ".svn"class WCFormatConverter:  "Performs WC format conversions."  root_path = None  error_on_unrecognized = True  force = False  verbosity = 0  def write_dir_format(self, format_nbr, dirname, paths):    """Attempt to write the WC format FORMAT_NBR to the entries file    for DIRNAME.  Throws LossyConversionException when not in --force    mode, and unconvertable WC data is encountered."""    # Avoid iterating in unversioned directories.    if not (get_adm_dir() in paths):      del paths[:]      return    # Process the entries file for this versioned directory.    if self.verbosity:      print("Processing directory '%s'" % dirname)    entries = Entries(os.path.join(dirname, get_adm_dir(), "entries"))    entries_parsed = True    if self.verbosity:      print("Parsing file '%s'" % entries.path)    try:      entries.parse(self.verbosity)    except UnrecognizedWCFormatException, e:      if self.error_on_unrecognized:        raise      sys.stderr.write("%s, skipping\n" % e)      sys.stderr.flush()      entries_parsed = False    if entries_parsed:      format = Format(os.path.join(dirname, get_adm_dir(), "format"))      if self.verbosity:        print("Updating file '%s'" % format.path)      format.write_format(format_nbr, self.verbosity)    else:      if self.verbosity:        print("Skipping file '%s'" % format.path)    if self.verbosity:      print("Checking whether WC format can be converted")    try:      entries.assert_valid_format(format_nbr, self.verbosity)    except LossyConversionException, e:      # In --force mode, ignore complaints about lossy conversion.      if self.force:        print("WARNING: WC format conversion will be lossy. Dropping "\              "field(s) %s " % ", ".join(e.lossy_fields))      else:        raise    if self.verbosity:      print("Writing WC format")    entries.write_format(format_nbr)  def change_wc_format(self, format_nbr):    """Walk all paths in a WC tree, and change their format to    FORMAT_NBR.  Throw LossyConversionException or NotImplementedError    if the WC format should not be converted, or is unrecognized."""    for dirpath, dirs, files in os.walk(self.root_path):      self.write_dir_format(format_nbr, dirpath, dirs + files)class Entries:  """Represents a .svn/entries file.  'The entries file' section in subversion/libsvn_wc/README is a  useful reference."""  # The name and index of each field composing an entry's record.  entry_fields = (    "name",    "kind",    "revision",    "url",    "repos",    "schedule",    "text-time",    "checksum",    "committed-date",    "committed-rev",    "last-author",    "has-props",    "has-prop-mods",    "cachable-props",    "present-props",    "conflict-old",    "conflict-new",    "conflict-wrk",    "prop-reject-file",    "copied",    "copyfrom-url",    "copyfrom-rev",    "deleted",    "absent",    "incomplete",    "uuid",    "lock-token",    "lock-owner",    "lock-comment",    "lock-creation-date",    "changelist",    "keep-local",    "working-size",    "depth",    "tree-conflicts",    "file-external",  )  # The format number.  format_nbr = -1  # How many bytes the format number takes in the file.  (The format number  # may have leading zeroes after using this script to convert format 10 to  # format 9 -- which would write the format number as '09'.)  format_nbr_bytes = -1  def __init__(self, path):    self.path = path    self.entries = []  def parse(self, verbosity=0):    """Parse the entries file.  Throw NotImplementedError if the WC    format is unrecognized."""    input = open(self.path, "r")    # Read WC format number from INPUT.  Validate that it    # is a supported format for conversion.    format_line = input.readline()    try:      self.format_nbr = int(format_line)      self.format_nbr_bytes = len(format_line.rstrip()) # remove '\n'    except ValueError:      self.format_nbr = -1      self.format_nbr_bytes = -1    if not self.format_nbr in LATEST_FORMATS.values():      raise UnrecognizedWCFormatException(self.format_nbr, self.path)    # Parse file into individual entries, to later inspect for    # non-convertable data.    entry = None    while True:      entry = self.parse_entry(input, verbosity)      if entry is None:        break      self.entries.append(entry)    input.close()  def assert_valid_format(self, format_nbr, verbosity=0):    if verbosity >= 2:      print("Validating format for entries file '%s'" % self.path)    for entry in self.entries:      if verbosity >= 3:        print("Validating format for entry '%s'" % entry.get_name())      try:        entry.assert_valid_format(format_nbr)      except LossyConversionException:        if verbosity >= 3:          sys.stderr.write("Offending entry:\n%s\n" % entry)          sys.stderr.flush()        raise  def parse_entry(self, input, verbosity=0):    "Read an individual entry from INPUT stream."    entry = None    while True:      line = input.readline()      if line in ("", "\x0c\n"):        # EOF or end of entry terminator encountered.        break      if entry is None:        entry = Entry()      # Retain the field value, ditching its field terminator ("\x0a").      entry.fields.append(line[:-1])    if entry is not None and verbosity >= 3:      sys.stdout.write(str(entry))      print("-" * 76)    return entry  def write_format(self, format_nbr):    # Overwrite all bytes of the format number (which are the first bytes in    # the file).  Overwrite format '10' by format '09', which will be converted    # to '9' by Subversion when it rewrites the file.  (Subversion 1.4 and later    # ignore leading zeroes in the format number.)    assert len(str(format_nbr)) <= self.format_nbr_bytes    format_string = '%0' + str(self.format_nbr_bytes) + 'd'    os.chmod(self.path, 0600)    output = open(self.path, "r+", 0)    output.write(format_string % format_nbr)    output.close()    os.chmod(self.path, 0400)class Entry:  "Describes an entry in a WC."  # Maps format numbers to indices of fields within an entry's record that must  # be retained when downgrading to that format.  must_retain_fields = {      # Not in 1.4: changelist, keep-local, depth, tree-conflicts, file-externals      8  : (30, 31, 33, 34, 35),      # Not in 1.5: tree-conflicts, file-externals      9  : (34, 35),      10 : (),      # Downgrading from format 11 (1.7-dev) to format 10 is not possible,      # because 11 does not use has-props and cachable-props (but 10 does).      # Naively downgrading in that situation causes properties to disappear      # from the wc.      #      # Downgrading from the 1.7 SQLite-based format to format 10 is not      # implemented.      }  def __init__(self):    self.fields = []  def assert_valid_format(self, format_nbr):    "Assure that conversion will be non-lossy by examining fields."    # Check whether lossy conversion is being attempted.    lossy_fields = []    for field_index in self.must_retain_fields[format_nbr]:      if len(self.fields) - 1 >= field_index and self.fields[field_index]:        lossy_fields.append(Entries.entry_fields[field_index])    if lossy_fields:      raise LossyConversionException(lossy_fields,        "Lossy WC format conversion requested for entry '%s'\n"        "Data for the following field(s) is unsupported by older versions "        "of\nSubversion, and is likely to be subsequently discarded, and/or "        "have\nunexpected side-effects: %s\n\n"        "WC format conversion was cancelled, use the --force option to "        "override\nthe default behavior."        % (self.get_name(), ", ".join(lossy_fields)))  def get_name(self):    "Return the name of this entry."    return len(self.fields) > 0 and self.fields[0] or ""  def __str__(self):    "Return all fields from this entry as a multi-line string."    rep = ""    for i in range(0, len(self.fields)):      rep += "[%s] %s\n" % (Entries.entry_fields[i], self.fields[i])    return repclass Format:  """Represents a .svn/format file."""  def __init__(self, path):    self.path = path  def write_format(self, format_nbr, verbosity=0):    format_string = '%d\n'    if os.path.exists(self.path):      if verbosity >= 1:        print("%s will be updated." % self.path)      os.chmod(self.path,0600)    else:      if verbosity >= 1:        print("%s does not exist, creating it." % self.path)    format = open(self.path, "w")    format.write(format_string % format_nbr)    format.close()    os.chmod(self.path, 0400)class LocalException(Exception):  """Root of local exception class hierarchy."""  passclass LossyConversionException(LocalException):  "Exception thrown when a lossy WC format conversion is requested."  def __init__(self, lossy_fields, str):    self.lossy_fields = lossy_fields    self.str = str  def __str__(self):    return self.strclass UnrecognizedWCFormatException(LocalException):  def __init__(self, format, path):    self.format = format    self.path = path  def __str__(self):    return ("Unrecognized WC format %d in '%s'; "            "only formats 8, 9, and 10 can be supported") % (self.format, self.path)def main():  try:    opts, args = my_getopt(sys.argv[1:], "vh?",                           ["debug", "force", "skip-unknown-format",                            "verbose", "help"])  except:    usage_and_exit("Unable to process arguments/options")  converter = WCFormatConverter()  # Process arguments.  if len(args) == 2:    converter.root_path = args[0]    svn_version = args[1]  else:    usage_and_exit()  # Process options.  debug = False  for opt, value in opts:    if opt in ("--help", "-h", "-?"):      usage_and_exit()    elif opt == "--force":      converter.force = True    elif opt == "--skip-unknown-format":      converter.error_on_unrecognized = False    elif opt in ("--verbose", "-v"):      converter.verbosity += 1    elif opt == "--debug":      debug = True    else:      usage_and_exit("Unknown option '%s'" % opt)  try:    new_format_nbr = LATEST_FORMATS[svn_version]  except KeyError:    usage_and_exit("Unsupported version number '%s'; "                   "only 1.4, 1.5, and 1.6 can be supported" % svn_version)  try:    converter.change_wc_format(new_format_nbr)  except LocalException, e:    if debug:      raise    sys.stderr.write("%s\n" % e)    sys.stderr.flush()    sys.exit(1)  print("Converted WC at '%s' into format %d for Subversion %s" % \        (converter.root_path, new_format_nbr, svn_version))if __name__ == "__main__":  main()
1 0
原创粉丝点击