Package moap :: Package vcs :: Module svn
[hide private]
[frames] | no frames]

Source Code for Module moap.vcs.svn

  1  # -*- Mode: Python; test-case-name: moap.test.test_vcs_svn -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3   
  4  """ 
  5  SVN functionality. 
  6  """ 
  7   
  8  import os 
  9  import commands 
 10  import re 
 11   
 12  from moap.util import util, log 
 13  from moap.vcs import vcs 
 14   
15 -def detect(path):
16 """ 17 Detect if the given source tree is using svn. 18 19 @return: True if the given path looks like a Subversion tree. 20 """ 21 if not os.path.exists(os.path.join(path, '.svn')): 22 log.debug('svn', 'Did not find .svn directory under %s' % path) 23 return False 24 25 for n in ['format', 'props', 'text-base']: 26 if not os.path.exists(os.path.join(path, '.svn', n)): 27 log.debug('svn', 'Did not find .svn/%s under %s' % (n, path)) 28 return False 29 30 return True
31
32 -class SVN(vcs.VCS):
33 name = 'Subversion' 34
35 - def getNotIgnored(self):
36 ret = [] 37 oldPath = os.getcwd() 38 39 os.chdir(self.path) 40 cmd = "svn status" 41 output = commands.getoutput(cmd) 42 lines = output.split("\n") 43 matcher = re.compile('^\?\s+(.*)') 44 for l in lines: 45 m = matcher.search(l) 46 if m: 47 path = m.expand("\\1") 48 ret.append(path) 49 50 # FIXME: would be nice to sort per directory 51 os.chdir(oldPath) 52 return ret
53
54 - def ignore(self, paths, commit=True):
55 oldPath = os.getcwd() 56 57 os.chdir(self.path) 58 # svn ignores files by editing the svn:ignore property on the parent 59 tree = self.createTree(paths) 60 toCommit = [] 61 for path in tree.keys(): 62 # read in old property 63 cmd = "svn propget svn:ignore %s" % path 64 (status, output) = commands.getstatusoutput(cmd) 65 lines = output.split("\n") 66 # svn 1.3.1 (r19032) 67 # $ svn propset svn:ignore --file - . 68 # svn: Reading from stdin is currently broken, so disabled 69 temp = util.writeTemp(lines + tree[path]) 70 # svn needs to use "." for the base directory 71 if path == '': 72 path = '.' 73 toCommit.append(path) 74 cmd = "svn propset svn:ignore --file %s %s" % (temp, path) 75 os.system(cmd) 76 os.unlink(temp) 77 78 if commit and toCommit: 79 cmd = "svn commit -m 'moap ignore' -N %s" % " ".join(toCommit) 80 os.system(cmd) 81 os.chdir(oldPath)
82
83 - def commit(self, paths, message):
84 # get all the parents as well 85 parents = [] 86 for p in paths: 87 while p: 88 p = os.path.dirname(p) 89 if p: 90 parents.append(p) 91 92 paths.extend(parents) 93 temp = util.writeTemp([message, ]) 94 paths = [os.path.join(self.path, p) for p in paths] 95 cmd = "svn commit --non-recursive --file %s %s" % ( 96 temp, " ".join(paths)) 97 status = os.system(cmd) 98 os.unlink(temp) 99 if status != 0: 100 return False 101 102 return True
103
104 - def diff(self, path):
105 # the diff can also contain svn-specific property changes 106 # we need to filter them to be a normal unified diff 107 # These blocks are recognizable because they go 108 # newline - Property changes on: - stuff - newline 109 # We parse in the C locale so we need to set it - see ticket #266 110 cmd = "LANG=C svn diff %s" % path 111 output = commands.getoutput(cmd) 112 return self.scrubPropertyChanges(output)
113
114 - def scrubPropertyChanges(self, output):
115 """ 116 Scrub the given diff output from property changes. 117 """ 118 reo = re.compile( 119 '^$\n' # starting empty line 120 '^Property changes on:.*?$\n' # Property changes line, non-greedy 121 '.*?' # all the other lines, non-greedy 122 '^$\n', # ending empty line 123 re.MULTILINE | re.DOTALL) # make sure we do multi-line 124 125 return reo.sub('', output)
126
127 - def getPropertyChanges(self, path):
128 ret = {} 129 130 cmd = "LANG=C svn diff %s" % path 131 # we add a newline so we can match each Property changes block by 132 # having it end on a newline, including the last block 133 output = commands.getoutput(cmd) + '\n' 134 135 # match Property changes blocks 136 reo = re.compile( 137 'Property changes on: (.*?)$\n' # Property changes line, non-greedy 138 '^_*$\n' # Divider line 139 '^(Name: .*?' # Property name block, non-greedy 140 '(?:Property)?)' # and stop at a possible next block 141 '^$\n' # and end on empty line 142 , re.MULTILINE | re.DOTALL) # make sure we do multi-line 143 144 # match Name: blocks within a file's property changes 145 reop = re.compile( 146 '^Name: (.*?)\n' # Property name block, non-greedy 147 , re.MULTILINE | re.DOTALL) # make sure we do multi-line 148 149 150 fileMatches = reo.findall(output) 151 for path, properties in fileMatches: 152 ret[path] = reop.findall(properties) 153 154 return ret
155
156 - def _getByStatus(self, path, status):
157 """ 158 @param status: one character indicating the status we want to get 159 all paths for. 160 """ 161 ret = [] 162 163 cmd = "svn status %s" % path 164 output = commands.getoutput(cmd) 165 166 for line in output.split('\n'): 167 if not line.startswith(status): 168 continue 169 170 ret.append(line[len('A + '):]) 171 172 return ret
173
174 - def getAdded(self, path):
175 return self._getByStatus(path, 'A')
176
177 - def getDeleted(self, path):
178 return self._getByStatus(path, 'D')
179
180 - def update(self, path):
181 cmd = "svn update %s" % path 182 status, output = commands.getstatusoutput(cmd) 183 if status != 0: 184 raise vcs.VCSException(output) 185 return output
186 187 VCSClass = SVN 188