aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'cvs2svn_lib/property_setters.py')
-rw-r--r--cvs2svn_lib/property_setters.py385
1 files changed, 0 insertions, 385 deletions
diff --git a/cvs2svn_lib/property_setters.py b/cvs2svn_lib/property_setters.py
deleted file mode 100644
index 7cf379e..0000000
--- a/cvs2svn_lib/property_setters.py
+++ /dev/null
@@ -1,385 +0,0 @@
-# (Be in -*- python -*- mode.)
-#
-# ====================================================================
-# Copyright (c) 2000-2008 CollabNet. All rights reserved.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at http://subversion.tigris.org/license-1.html.
-# If newer versions of this license are posted there, you may use a
-# newer version instead, at your option.
-#
-# This software consists of voluntary contributions made by many
-# individuals. For exact contribution history, see the revision
-# history and logs, available at http://cvs2svn.tigris.org/.
-# ====================================================================
-
-"""This module contains classes to set Subversion properties on files."""
-
-
-import os
-import re
-import fnmatch
-import ConfigParser
-from cStringIO import StringIO
-
-from cvs2svn_lib.common import warning_prefix
-from cvs2svn_lib.log import Log
-
-
-class SVNPropertySetter:
- """Abstract class for objects that can set properties on a SVNCommitItem."""
-
- def set_properties(self, s_item):
- """Set any properties that can be determined for S_ITEM.
-
- S_ITEM is an instance of SVNCommitItem. This method should modify
- S_ITEM.svn_props in place."""
-
- raise NotImplementedError
-
-
-class CVSRevisionNumberSetter(SVNPropertySetter):
- """Set the cvs2svn:cvs-rev property to the CVS revision number."""
-
- propname = 'cvs2svn:cvs-rev'
-
- def set_properties(self, s_item):
- if self.propname in s_item.svn_props:
- return
-
- s_item.svn_props[self.propname] = s_item.cvs_rev.rev
- s_item.svn_props_changed = True
-
-
-class ExecutablePropertySetter(SVNPropertySetter):
- """Set the svn:executable property based on cvs_rev.cvs_file.executable."""
-
- propname = 'svn:executable'
-
- def set_properties(self, s_item):
- if self.propname in s_item.svn_props:
- return
-
- if s_item.cvs_rev.cvs_file.executable:
- s_item.svn_props[self.propname] = '*'
-
-
-class CVSBinaryFileEOLStyleSetter(SVNPropertySetter):
- """Set the eol-style to None for files with CVS mode '-kb'."""
-
- propname = 'svn:eol-style'
-
- def set_properties(self, s_item):
- if self.propname in s_item.svn_props:
- return
-
- if s_item.cvs_rev.cvs_file.mode == 'b':
- s_item.svn_props[self.propname] = None
-
-
-class MimeMapper(SVNPropertySetter):
- """A class that provides mappings from file names to MIME types."""
-
- propname = 'svn:mime-type'
-
- def __init__(self, mime_types_file):
- self.mappings = { }
-
- for line in file(mime_types_file):
- if line.startswith("#"):
- continue
-
- # format of a line is something like
- # text/plain c h cpp
- extensions = line.split()
- if len(extensions) < 2:
- continue
- type = extensions.pop(0)
- for ext in extensions:
- if ext in self.mappings and self.mappings[ext] != type:
- Log().error(
- "%s: ambiguous MIME mapping for *.%s (%s or %s)\n"
- % (warning_prefix, ext, self.mappings[ext], type)
- )
- self.mappings[ext] = type
-
- def set_properties(self, s_item):
- if self.propname in s_item.svn_props:
- return
-
- basename, extension = os.path.splitext(s_item.cvs_rev.cvs_file.basename)
-
- # Extension includes the dot, so strip it (will leave extension
- # empty if filename ends with a dot, which is ok):
- extension = extension[1:]
-
- # If there is no extension (or the file ends with a period), use
- # the base name for mapping. This allows us to set mappings for
- # files such as README or Makefile:
- if not extension:
- extension = basename
-
- mime_type = self.mappings.get(extension, None)
- if mime_type is not None:
- s_item.svn_props[self.propname] = mime_type
-
-
-class AutoPropsPropertySetter(SVNPropertySetter):
- """Set arbitrary svn properties based on an auto-props configuration.
-
- This class supports case-sensitive or case-insensitive pattern
- matching. The command-line default is case-insensitive behavior,
- consistent with Subversion (see
- http://subversion.tigris.org/issues/show_bug.cgi?id=2036).
-
- As a special extension to Subversion's auto-props handling, if a
- property name is preceded by a '!' then that property is forced to
- be left unset.
-
- If a property specified in auto-props has already been set to a
- different value, print a warning and leave the old property value
- unchanged.
-
- Python's treatment of whitespaces in the ConfigParser module is
- buggy and inconsistent. Usually spaces are preserved, but if there
- is at least one semicolon in the value, and the *first* semicolon is
- preceded by a space, then that is treated as the start of a comment
- and the rest of the line is silently discarded."""
-
- property_name_pattern = r'(?P<name>[^\!\=\s]+)'
- property_unset_re = re.compile(
- r'^\!\s*' + property_name_pattern + r'$'
- )
- property_set_re = re.compile(
- r'^' + property_name_pattern + r'\s*\=\s*(?P<value>.*)$'
- )
- property_novalue_re = re.compile(
- r'^' + property_name_pattern + r'$'
- )
-
- quoted_re = re.compile(
- r'^([\'\"]).*\1$'
- )
- comment_re = re.compile(r'\s;')
-
- class Pattern:
- """Describes the properties to be set for files matching a pattern."""
-
- def __init__(self, pattern, propdict):
- # A glob-like pattern:
- self.pattern = pattern
- # A dictionary of properties that should be set:
- self.propdict = propdict
-
- def match(self, basename):
- """Does the file with the specified basename match pattern?"""
-
- return fnmatch.fnmatch(basename, self.pattern)
-
- def __init__(self, configfilename, ignore_case=True):
- config = ConfigParser.ConfigParser()
- if ignore_case:
- self.transform_case = self.squash_case
- else:
- config.optionxform = self.preserve_case
- self.transform_case = self.preserve_case
-
- configtext = open(configfilename).read()
- if self.comment_re.search(configtext):
- Log().warn(
- '%s: Please be aware that a space followed by a\n'
- 'semicolon is sometimes treated as a comment in configuration\n'
- 'files. This pattern was seen in\n'
- ' %s\n'
- 'Please make sure that you have not inadvertently commented\n'
- 'out part of an important line.'
- % (warning_prefix, configfilename,)
- )
-
- config.readfp(StringIO(configtext), configfilename)
- self.patterns = []
- sections = config.sections()
- sections.sort()
- for section in sections:
- if self.transform_case(section) == 'auto-props':
- patterns = config.options(section)
- patterns.sort()
- for pattern in patterns:
- value = config.get(section, pattern)
- if value:
- self._add_pattern(pattern, value)
-
- def squash_case(self, s):
- return s.lower()
-
- def preserve_case(self, s):
- return s
-
- def _add_pattern(self, pattern, props):
- propdict = {}
- if self.quoted_re.match(pattern):
- Log().warn(
- '%s: Quoting is not supported in auto-props; please verify rule\n'
- 'for %r. (Using pattern including quotation marks.)\n'
- % (warning_prefix, pattern,)
- )
- for prop in props.split(';'):
- prop = prop.strip()
- m = self.property_unset_re.match(prop)
- if m:
- name = m.group('name')
- Log().debug(
- 'auto-props: For %r, leaving %r unset.' % (pattern, name,)
- )
- propdict[name] = None
- continue
-
- m = self.property_set_re.match(prop)
- if m:
- name = m.group('name')
- value = m.group('value')
- if self.quoted_re.match(value):
- Log().warn(
- '%s: Quoting is not supported in auto-props; please verify\n'
- 'rule %r for pattern %r. (Using value\n'
- 'including quotation marks.)\n'
- % (warning_prefix, prop, pattern,)
- )
- Log().debug(
- 'auto-props: For %r, setting %r to %r.' % (pattern, name, value,)
- )
- propdict[name] = value
- continue
-
- m = self.property_novalue_re.match(prop)
- if m:
- name = m.group('name')
- Log().debug(
- 'auto-props: For %r, setting %r to the empty string'
- % (pattern, name,)
- )
- propdict[name] = ''
- continue
-
- Log().warn(
- '%s: in auto-props line for %r, value %r cannot be parsed (ignored)'
- % (warning_prefix, pattern, prop,)
- )
-
- self.patterns.append(self.Pattern(self.transform_case(pattern), propdict))
-
- def get_propdict(self, cvs_file):
- basename = self.transform_case(cvs_file.basename)
- propdict = {}
- for pattern in self.patterns:
- if pattern.match(basename):
- for (key,value) in pattern.propdict.items():
- if key in propdict:
- if propdict[key] != value:
- Log().warn(
- "Contradictory values set for property '%s' for file %s."
- % (key, cvs_file,))
- else:
- propdict[key] = value
-
- return propdict
-
- def set_properties(self, s_item):
- propdict = self.get_propdict(s_item.cvs_rev.cvs_file)
- for (k,v) in propdict.items():
- if k in s_item.svn_props:
- if s_item.svn_props[k] != v:
- Log().warn(
- "Property '%s' already set to %r for file %s; "
- "auto-props value (%r) ignored."
- % (k, s_item.svn_props[k], s_item.cvs_rev.cvs_path, v,))
- else:
- s_item.svn_props[k] = v
-
-
-class CVSBinaryFileDefaultMimeTypeSetter(SVNPropertySetter):
- """If the file is binary and its svn:mime-type property is not yet
- set, set it to 'application/octet-stream'."""
-
- propname = 'svn:mime-type'
-
- def set_properties(self, s_item):
- if self.propname in s_item.svn_props:
- return
-
- if s_item.cvs_rev.cvs_file.mode == 'b':
- s_item.svn_props[self.propname] = 'application/octet-stream'
-
-
-class EOLStyleFromMimeTypeSetter(SVNPropertySetter):
- """Set svn:eol-style based on svn:mime-type.
-
- If svn:mime-type is known but svn:eol-style is not, then set
- svn:eol-style based on svn:mime-type as follows: if svn:mime-type
- starts with 'text/', then set svn:eol-style to native; otherwise,
- force it to remain unset. See also issue #39."""
-
- propname = 'svn:eol-style'
-
- def set_properties(self, s_item):
- if self.propname in s_item.svn_props:
- return
-
- if s_item.svn_props.get('svn:mime-type', None) is not None:
- if s_item.svn_props['svn:mime-type'].startswith("text/"):
- s_item.svn_props[self.propname] = 'native'
- else:
- s_item.svn_props[self.propname] = None
-
-
-class DefaultEOLStyleSetter(SVNPropertySetter):
- """Set the eol-style if one has not already been set."""
-
- propname = 'svn:eol-style'
-
- def __init__(self, value):
- """Initialize with the specified default VALUE."""
-
- self.value = value
-
- def set_properties(self, s_item):
- if self.propname in s_item.svn_props:
- return
-
- s_item.svn_props[self.propname] = self.value
-
-
-class SVNBinaryFileKeywordsPropertySetter(SVNPropertySetter):
- """Turn off svn:keywords for files with binary svn:eol-style."""
-
- propname = 'svn:keywords'
-
- def set_properties(self, s_item):
- if self.propname in s_item.svn_props:
- return
-
- if not s_item.svn_props.get('svn:eol-style'):
- s_item.svn_props[self.propname] = None
-
-
-class KeywordsPropertySetter(SVNPropertySetter):
- """If the svn:keywords property is not yet set, set it based on the
- file's mode. See issue #2."""
-
- propname = 'svn:keywords'
-
- def __init__(self, value):
- """Use VALUE for the value of the svn:keywords property if it is
- to be set."""
-
- self.value = value
-
- def set_properties(self, s_item):
- if self.propname in s_item.svn_props:
- return
-
- if s_item.cvs_rev.cvs_file.mode in [None, 'kv', 'kvl']:
- s_item.svn_props[self.propname] = self.value
-
-