Break out of loop correctly when the first file difference is found.
[cvs2svn.git] / cvs2svn_lib / cvs_revision_manager.py
blobb83d842f48f9c8a119441ae82b65c43a08855164
1 # (Be in -*- python -*- mode.)
3 # ====================================================================
4 # Copyright (c) 2000-2008 CollabNet. All rights reserved.
6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms
8 # are also available at http://subversion.tigris.org/license-1.html.
9 # If newer versions of this license are posted there, you may use a
10 # newer version instead, at your option.
12 # This software consists of voluntary contributions made by many
13 # individuals. For exact contribution history, see the revision
14 # history and logs, available at http://cvs2svn.tigris.org/.
15 # ====================================================================
17 """Access the CVS repository via CVS's 'cvs' command."""
20 from cvs2svn_lib.common import FatalError
21 from cvs2svn_lib.common import canonicalize_eol
22 from cvs2svn_lib.process import check_command_runs
23 from cvs2svn_lib.process import get_command_output
24 from cvs2svn_lib.process import CommandFailedException
25 from cvs2svn_lib.context import Ctx
26 from cvs2svn_lib.revision_manager import RevisionReader
27 from cvs2svn_lib.apple_single_filter import get_maybe_apple_single
30 class CVSRevisionReader(RevisionReader):
31 """A RevisionReader that reads the contents via CVS."""
33 # Different versions of CVS support different global options. Here
34 # are the global options that we try to use, in order of decreasing
35 # preference:
36 _possible_global_options = [
37 ['-Q', '-R', '-f'],
38 ['-Q', '-R'],
39 ['-Q', '-f'],
40 ['-Q'],
41 ['-q', '-R', '-f'],
42 ['-q', '-R'],
43 ['-q', '-f'],
44 ['-q'],
47 def __init__(self, cvs_executable, global_options=None):
48 """Initialize a CVSRevisionReader.
50 CVS_EXECUTABLE is the CVS command (possibly including the full
51 path to the executable; otherwise it is sought in the $PATH).
52 GLOBAL_ARGUMENTS, if specified, should be a list of global options
53 that are passed to the CVS command before the subcommand. If
54 GLOBAL_ARGUMENTS is not specified, then each of the possibilities
55 listed in _possible_global_options is checked in order until one
56 is found that runs successfully and without any output to stderr."""
58 self.cvs_executable = cvs_executable
60 if global_options is None:
61 for global_options in self._possible_global_options:
62 try:
63 self._check_cvs_runs(global_options)
64 except CommandFailedException, e:
65 pass
66 else:
67 break
68 else:
69 raise FatalError(
70 '%s\n'
71 'Please check that cvs is installed and in your PATH.' % (e,)
73 else:
74 try:
75 self._check_cvs_runs(global_options)
76 except CommandFailedException, e:
77 raise FatalError(
78 '%s\n'
79 'Please check that cvs is installed and in your PATH and that\n'
80 'the global options that you specified (%r) are correct.'
81 % (e, global_options,)
84 # The global options were OK; use them for all CVS invocations.
85 self.global_options = global_options
87 def _check_cvs_runs(self, global_options):
88 """Check that CVS can be started.
90 Try running 'cvs --version' with the current setting for
91 self.cvs_executable and the specified global_options. If not
92 successful, raise a CommandFailedException."""
94 check_command_runs(
95 [self.cvs_executable] + global_options + ['--version'],
96 self.cvs_executable,
99 def get_content(self, cvs_rev):
100 project = cvs_rev.cvs_file.project
101 pipe_cmd = [
102 self.cvs_executable
103 ] + self.global_options + [
104 '-d', ':local:' + project.cvs_repository_root,
105 'co',
106 '-r' + cvs_rev.rev,
107 '-p'
109 if cvs_rev.get_property('_keyword_handling') == 'collapsed':
110 pipe_cmd.append('-kk')
111 pipe_cmd.append(project.cvs_module + cvs_rev.cvs_path)
112 data = get_command_output(pipe_cmd)
114 if Ctx().decode_apple_single:
115 # Insert a filter to decode any files that are in AppleSingle
116 # format:
117 data = get_maybe_apple_single(data)
119 eol_fix = cvs_rev.get_property('_eol_fix')
120 if eol_fix:
121 data = canonicalize_eol(data, eol_fix)
123 return data