#!/usr/bin/env python
#
# change-svn-wc-format.py: Change the format of a Subversion working copy.
#
# ====================================================================
#    Licensed to the Subversion Corporation (SVN Corp.) under one
#    or more contributor license agreements.  See the NOTICE file
#    distributed with this work for additional information
#    regarding copyright ownership.  The SVN Corp. 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 sys
import os
import getopt
try:
  my_getopt = getopt.gnu_getopt
except 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 --help

Change 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.collab.net/repos/svn/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 as 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 as 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, 0o600)
    output = open(self.path, "r+")
    output.write(format_string % format_nbr)
    output.close()
    os.chmod(self.path, 0o400)

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 rep

class 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,0o600)
    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, 0o400)

class LocalException(Exception):
  """Root of local exception class hierarchy."""
  pass

class 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.str

class 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 as 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()
