LSSTApplications  1.1.2+25,10.0+13,10.0+132,10.0+133,10.0+224,10.0+41,10.0+8,10.0-1-g0f53050+14,10.0-1-g4b7b172+19,10.0-1-g61a5bae+98,10.0-1-g7408a83+3,10.0-1-gc1e0f5a+19,10.0-1-gdb4482e+14,10.0-11-g3947115+2,10.0-12-g8719d8b+2,10.0-15-ga3f480f+1,10.0-2-g4f67435,10.0-2-gcb4bc6c+26,10.0-28-gf7f57a9+1,10.0-3-g1bbe32c+14,10.0-3-g5b46d21,10.0-4-g027f45f+5,10.0-4-g86f66b5+2,10.0-4-gc4fccf3+24,10.0-40-g4349866+2,10.0-5-g766159b,10.0-5-gca2295e+25,10.0-6-g462a451+1
LSSTDataManagementBasePackage
svn.py
Go to the documentation of this file.
1 #
2 # A simple python interface to svn, using os.popen
3 #
4 # If ever we want to do anything clever, we should use one of
5 # the supported svn/python packages
6 #
7 import os, re, sys
8 
9 def isSvnFile(file):
10  """Is file under svn control?"""
11 
12  return re.search(r"is not a working copy",
13  "".join(os.popen("svn info %s 2>&1" % file).readlines())) == None
14 
15 def getInfo(file="."):
16  """Return a dictionary of all the information returned by "svn info" for the specified file"""
17 
18  if not isSvnFile(file):
19  raise RuntimeError, "%s is not under svn control" % file
20 
21  infoList = os.popen("svn info %s" % file).readlines()
22 
23  info = {}
24  for line in infoList:
25  mat = re.search(r"^([^:]+)\s*:\s*(.*)", line)
26  if mat:
27  info[mat.group(1)] = mat.group(2)
28 
29  return info
30 
31 def isTrunk(file="."):
32  """Is file on the trunk?"""
33 
34  info = getInfo(file)
35 
36  return re.search(r"/trunk($|/)", info["URL"]) != None
37 
38 def revision(file=None, lastChanged=False):
39  """Return file's Revision as a string; if file is None return
40  a tuple (oldestRevision, youngestRevision, flags) as reported
41  by svnversion; e.g. (4123, 4168, ("M", "S")) (oldestRevision
42  and youngestRevision may be equal)
43  """
44 
45  if file:
46  info = getInfo(file)
47 
48  if lastChanged:
49  return info["Last Changed Rev"]
50  else:
51  return info["Revision"]
52 
53  if lastChanged:
54  raise RuntimeError, "lastChanged makes no sense if file is None"
55 
56  res = os.popen("svnversion . 2>&1").readline()
57 
58  if res == "exported\n":
59  raise RuntimeError, "No svn revision information is available"
60 
61  versionRe = r"^(?P<oldest>\d+)(:(?P<youngest>\d+))?(?P<flags>[MS]*)"
62  mat = re.search(versionRe, res)
63  if mat:
64  matches = mat.groupdict()
65  if not matches["youngest"]:
66  matches["youngest"] = matches["oldest"]
67  # OK, we have only one revision present. Find the newest revision
68  # that actually changed anything in this product and ignore "oldest" (#522)
69  res = os.popen("svnversion --committed . 2>&1").readline()
70  mat = re.search(versionRe, res)
71  if mat:
72  matches = mat.groupdict()
73  return matches["youngest"], matches["youngest"], tuple(matches["flags"])
74 
75  return matches["oldest"], matches["youngest"], tuple(matches["flags"])
76 
77  raise RuntimeError, ("svnversion returned unexpected result \"%s\"" % res[:-1])
78 
79 #
80 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
81 #
82 def guessVersionName(HeadURL):
83  """Guess a version name given a HeadURL"""
84 
85  if re.search(r"/trunk$", HeadURL):
86  versionName = ""
87  elif re.search(r"/branches/(.+)$", HeadURL):
88  versionName = "branch_%s+" % re.search(r"/branches/(.+)$", HeadURL).group(1)
89  elif re.search(r"/tags/(.+)$", HeadURL):
90  versionName = "%s" % re.search(r"/tags/(.*)$", HeadURL).group(1)
91 
92  return versionName # no need for a "+svnXXXX"
93  elif re.search(r"/tickets/(\d+)$", HeadURL):
94  versionName = "ticket_%s+" % re.search(r"/tickets/(\d+)$", HeadURL).group(1)
95  else:
96  print >> sys.stderr, "Unable to guess versionName name from %s" % HeadURL
97  versionName = "unknown+"
98 
99  try: # Try to lookup the svn versionName
100  (oldest, youngest, flags) = revision()
101 
102  okVersion = True
103  if "M" in flags:
104  msg = "You are installing, but have unchecked in files"
105  okVersion = False
106  if "S" in flags:
107  msg = "You are installing, but have switched SVN URLs"
108  okVersion = False
109  if oldest != youngest:
110  msg = "You have a range of revisions in your tree (%s:%s); adopting %s" % \
111  (oldest, youngest, youngest)
112  okVersion = False
113 
114  if not okVersion:
115  raise RuntimeError, ("Problem with determining svn revision: %s" % msg)
116 
117  versionName += "svn" + youngest
118  except IOError:
119  return "unknown"
120 
121  return versionName
122 
123 def parseVersionName(versionName):
124  """A callback that knows about the LSST convention that a tagname such as
125  ticket_374
126  means the top of ticket 374, and
127  ticket_374+svn6021
128  means revision 6021 on ticket 374. You may replace "ticket" with "branch" if you wish
129 
130  The "versionName" may actually be the directory part of a URL, and ".../(branches|tags|tickets)/tagname"
131  is also supported
132  """
133 
134  mat = re.search(r"/(branche|tag|ticket)s/(\d+(?:\.\d+)*)(?:([-+])((svn)?(\d+)))?$", versionName)
135  if not mat:
136  mat = re.search(r"/(branch|ticket)_(\d+)(?:([-+])svn(\d+))?$", versionName)
137  if mat:
138  type = mat.group(1)
139  if type == "branches":
140  type = "branch"
141  ticket = mat.group(2)
142  pm = mat.group(3) # + or -
143  revision = mat.group(4)
144  if revision:
145  revision = re.sub("^svn", "", revision)
146 
147  return (type, ticket, revision, pm)
148 
149  return (None, None, None, None)