[18] | 1 | #!/usr/bin/env python |
---|
| 2 | |
---|
| 3 | """ This script (rcvs) executes cvs on a remote cvs client. |
---|
| 4 | Useful when cvs access is only allowed from one particular host. |
---|
| 5 | |
---|
| 6 | Definitions |
---|
| 7 | CVS server: host where CVS repository resides |
---|
| 8 | CVS client: host from which access to CVS server is allowed |
---|
| 9 | local host: host that must access CVS repository through CVS client |
---|
| 10 | |
---|
| 11 | |
---|
| 12 | Assumptions: |
---|
| 13 | |
---|
| 14 | 1:CVS client can be reached from local host without passwords |
---|
| 15 | using ssh and rsync |
---|
| 16 | |
---|
| 17 | 2:Usernames on CVS client and CVS server are the same |
---|
| 18 | |
---|
| 19 | 3:Details about CVS Host are supplied at the top of this script |
---|
| 20 | |
---|
| 21 | 4:CVSROOT environment variable point to CVS client so that username and CVS client |
---|
| 22 | can be inferred automatically |
---|
| 23 | |
---|
| 24 | 5:Each user has a directory called sandpit in their home directory on the CVS client |
---|
| 25 | |
---|
| 26 | 6:CVS client has a UNIX/Linux file structure |
---|
| 27 | |
---|
| 28 | 7:That user has performed a CVS login once from CVS client to CVS host |
---|
| 29 | |
---|
| 30 | |
---|
| 31 | Modus operandi: |
---|
| 32 | |
---|
| 33 | The rcvs script will do updates, add and commit plus download (unique to rcvs) |
---|
| 34 | Commands such as tag, remove etc mus be done on cvs client. |
---|
| 35 | |
---|
| 36 | |
---|
| 37 | Examples: |
---|
| 38 | |
---|
| 39 | |
---|
| 40 | rcvs checkout repository (checkout and download repository from cvs client) |
---|
| 41 | |
---|
| 42 | rcvs add [files...] (add named files to repository) |
---|
| 43 | |
---|
| 44 | rcvs update [files...] (update named files from cvs server) |
---|
| 45 | |
---|
| 46 | rcvs com -m "msg" [files...] (Commit changes with log message) |
---|
| 47 | |
---|
| 48 | rcvs log [files...] (List log history for files) |
---|
| 49 | |
---|
| 50 | rcvs download repository (download repository from cvs client) |
---|
| 51 | |
---|
| 52 | |
---|
| 53 | If files are omitted command will work on all files in repository. |
---|
| 54 | |
---|
| 55 | SSH Setup |
---|
| 56 | To get cgywin ssh working, wothout using passwords; |
---|
| 57 | 1) Set the environment variable |
---|
| 58 | CYGWIN = smbntsec |
---|
| 59 | 2) In windows explorer/permissions/security, make sure the private key has |
---|
| 60 | only 1 user |
---|
| 61 | |
---|
| 62 | Copyright 2004 |
---|
| 63 | Ole Nielsen and Duncan Gray |
---|
| 64 | Geoscience Australia |
---|
| 65 | """ |
---|
| 66 | |
---|
| 67 | #Details about CVS Host |
---|
| 68 | protocol = 'pserver' |
---|
| 69 | cvs_host = 'cuttlefish.anu.edu.au' |
---|
| 70 | cvs_dir = '/home/cvs' |
---|
| 71 | |
---|
| 72 | |
---|
| 73 | rsep = '/' #Separator on cvs client |
---|
| 74 | from os import sep #Separator on local machine |
---|
| 75 | |
---|
| 76 | import sys, os |
---|
| 77 | |
---|
| 78 | #Get Username and cvs client - assumed to be the same on cvs host and remote cvs client |
---|
| 79 | |
---|
| 80 | s = os.getenv('CVSROOT') |
---|
| 81 | username = '' |
---|
| 82 | cvs_client = '' |
---|
| 83 | if len(s) > 0: |
---|
| 84 | atsign = s.index('@') |
---|
| 85 | |
---|
| 86 | #Username |
---|
| 87 | i = atsign-1 |
---|
| 88 | while i > 0 and s[i] != ':': |
---|
| 89 | username = s[i] + username |
---|
| 90 | i -= 1 |
---|
| 91 | |
---|
| 92 | #CVS client |
---|
| 93 | i = atsign+1 |
---|
| 94 | while i < len(s) and s[i] != ':': |
---|
| 95 | cvs_client += s[i] |
---|
| 96 | i += 1 |
---|
| 97 | |
---|
| 98 | if len(username) == 0: |
---|
| 99 | msg = 'Could not infer user name from environment variable CVSROOT (%s)' %s |
---|
| 100 | raise msg |
---|
| 101 | |
---|
| 102 | if len(cvs_client) == 0: |
---|
| 103 | msg = 'Could not infer CVS client from environment variable CVSROOT (%s)' %s |
---|
| 104 | raise msg |
---|
| 105 | |
---|
| 106 | |
---|
| 107 | #CVSROOT = ':pserver:%s@cuttlefish.anu.edu.au:/home/cvs' %username |
---|
| 108 | CVSROOT = ':%s:%s@%s:%s' %(protocol, username, cvs_host, cvs_dir) |
---|
| 109 | |
---|
| 110 | |
---|
| 111 | #specify location of remote repositories (assuming UNIX separators) |
---|
| 112 | sandpit = '~' + rsep + 'sandpit' |
---|
| 113 | |
---|
| 114 | |
---|
| 115 | def run(cmd): |
---|
| 116 | import os |
---|
| 117 | print cmd |
---|
| 118 | os.system(cmd) |
---|
| 119 | |
---|
| 120 | |
---|
| 121 | def upload(dir): |
---|
| 122 | files=get_cvsfiles() |
---|
| 123 | #s = 'rsync --cvs-exclude -qavz %s %s@%s:%s'\ |
---|
| 124 | s = 'rsync -qavz %s %s@%s:%s' %(files, username, cvs_client, sandpit + rsep + dir) |
---|
| 125 | print '---------- UPLOADING -------------' |
---|
| 126 | run(s) |
---|
| 127 | |
---|
| 128 | |
---|
| 129 | def download(dir): |
---|
| 130 | import os |
---|
| 131 | |
---|
| 132 | s = 'rsync -qavz %s@%s:%s' %(username, cvs_client, sandpit) +\ |
---|
| 133 | rsep + dir + rsep + '* .' |
---|
| 134 | print '---------- DOWNLOADING -------------' |
---|
| 135 | run(s) |
---|
| 136 | |
---|
| 137 | |
---|
| 138 | def cvscmd(dir, cmd, args): |
---|
| 139 | x = '' |
---|
| 140 | for arg in args: |
---|
| 141 | x += str(arg) + ' ' |
---|
| 142 | |
---|
| 143 | s = 'ssh -X %s@%s "cd %s; cvs %s %s"' %(username, cvs_client, |
---|
| 144 | sandpit + rsep + dir, |
---|
| 145 | cmd, x) |
---|
| 146 | print '---------- CVS OUTPUT -------------' |
---|
| 147 | run(s) |
---|
| 148 | |
---|
| 149 | |
---|
| 150 | |
---|
| 151 | #FIXME: Not done yet and maybe it shouldn't |
---|
| 152 | def get_cvsfiles(): |
---|
| 153 | """Get files that are registered under CVS |
---|
| 154 | """ |
---|
| 155 | import os |
---|
| 156 | |
---|
| 157 | #Get name of local repository |
---|
| 158 | localdir = os.getcwd() |
---|
| 159 | |
---|
| 160 | if not 'CVS' in os.listdir(localdir): |
---|
| 161 | raise 'No CVS directory in current directory' |
---|
| 162 | |
---|
| 163 | FN = localdir + sep + 'CVS' + sep + 'Entries' |
---|
| 164 | try: |
---|
| 165 | fid = open(FN) |
---|
| 166 | except: |
---|
| 167 | msg = 'Could not open %s' %FN |
---|
| 168 | raise msg |
---|
| 169 | else: |
---|
| 170 | files = '' |
---|
| 171 | for entry in fid.readlines(): |
---|
| 172 | #print entry |
---|
| 173 | pass |
---|
| 174 | |
---|
| 175 | |
---|
| 176 | return '*' |
---|
| 177 | |
---|
| 178 | |
---|
| 179 | def get_repository(): |
---|
| 180 | """Get name of CVS repository from CVS directory |
---|
| 181 | """ |
---|
| 182 | import os |
---|
| 183 | |
---|
| 184 | #Get name of local repository |
---|
| 185 | localdir = os.getcwd() |
---|
| 186 | |
---|
| 187 | if not 'CVS' in os.listdir(localdir): |
---|
| 188 | raise 'No CVS directory in current directory' |
---|
| 189 | |
---|
| 190 | |
---|
| 191 | FN = localdir + sep + 'CVS' + sep + 'Repository' |
---|
| 192 | try: |
---|
| 193 | fid = open(FN) |
---|
| 194 | except: |
---|
| 195 | msg = 'Could not open %s' %FN |
---|
| 196 | raise msg |
---|
| 197 | else: |
---|
| 198 | repository = fid.readlines()[0].strip() |
---|
| 199 | |
---|
| 200 | |
---|
| 201 | #Get actual name of local repository |
---|
| 202 | local = os.path.split(localdir)[1] |
---|
| 203 | |
---|
| 204 | #if local != repository: |
---|
| 205 | # msg = 'Local directory (%s) and ' %local |
---|
| 206 | # msg += 'CVS repository (%s) must have the same name' %repository |
---|
| 207 | # raise msg |
---|
| 208 | |
---|
| 209 | return repository |
---|
| 210 | |
---|
| 211 | |
---|
| 212 | if len(sys.argv) > 1: |
---|
| 213 | arg = sys.argv[1] |
---|
| 214 | |
---|
| 215 | if arg.find('upd') == 0: |
---|
| 216 | dir = get_repository() |
---|
| 217 | upload(dir) |
---|
| 218 | cvscmd(dir, 'update', sys.argv[2:]) |
---|
| 219 | download(dir) |
---|
| 220 | |
---|
| 221 | |
---|
| 222 | if arg.find('com') == 0 or arg.find('ci') == 0: |
---|
| 223 | dir = get_repository() |
---|
| 224 | upload(dir) |
---|
| 225 | |
---|
| 226 | args = sys.argv[2:] |
---|
| 227 | |
---|
| 228 | try: |
---|
| 229 | i = args.index('-m') |
---|
| 230 | except: |
---|
| 231 | comment = 'None' |
---|
| 232 | remaining_args = args |
---|
| 233 | else: |
---|
| 234 | #We have a text argument for the log file |
---|
| 235 | comment = '%s' %(args[i+1]) |
---|
| 236 | if len(comment) == 0: |
---|
| 237 | comment = 'None' |
---|
| 238 | remaining_args = args[:i]+args[i+2:] |
---|
| 239 | |
---|
| 240 | command = 'commit -m """%s"""' %comment |
---|
| 241 | #cvscmd(dir, 'update', remaining_args) |
---|
| 242 | cvscmd(dir, command, remaining_args) |
---|
| 243 | download(dir) |
---|
| 244 | |
---|
| 245 | |
---|
| 246 | if arg.find('add') == 0: |
---|
| 247 | dir = get_repository() |
---|
| 248 | upload(dir) |
---|
| 249 | cvscmd(dir, 'add', sys.argv[2:]) |
---|
| 250 | download(dir) |
---|
| 251 | |
---|
| 252 | |
---|
| 253 | if arg.find('log') == 0: |
---|
| 254 | dir = get_repository() |
---|
| 255 | upload(dir) |
---|
| 256 | cvscmd(dir, 'log', sys.argv[2:]) |
---|
| 257 | |
---|
| 258 | if arg.find('diff') == 0: |
---|
| 259 | dir = get_repository() |
---|
| 260 | upload(dir) |
---|
| 261 | cvscmd(dir, 'diff', sys.argv[2:]) |
---|
| 262 | |
---|
| 263 | if arg.find('annotate') == 0: |
---|
| 264 | dir = get_repository() |
---|
| 265 | upload(dir) |
---|
| 266 | cvscmd(dir, 'annotate', sys.argv[2:]) |
---|
| 267 | |
---|
| 268 | |
---|
| 269 | |
---|
| 270 | #FIXME: Maybe Obsolete |
---|
| 271 | if arg.find('down') == 0: |
---|
| 272 | import os |
---|
| 273 | if len(sys.argv) == 3: |
---|
| 274 | arg = sys.argv[2] |
---|
| 275 | |
---|
| 276 | os.mkdir(arg) #Create local copy of repository |
---|
| 277 | os.chdir(arg) |
---|
| 278 | download(arg) |
---|
| 279 | |
---|
| 280 | |
---|
| 281 | if arg.find('co') == 0 or arg.find('checkout') == 0: |
---|
| 282 | import os |
---|
| 283 | if len(sys.argv) == 3: |
---|
| 284 | arg = sys.argv[2] |
---|
| 285 | |
---|
| 286 | #Create local copy of repository |
---|
| 287 | try: |
---|
| 288 | os.mkdir(arg) |
---|
| 289 | except OSError: |
---|
| 290 | pass |
---|
| 291 | #msg = 'Could not create directory %s' %arg |
---|
| 292 | #raise msg |
---|
| 293 | |
---|
| 294 | os.chdir(arg) |
---|
| 295 | |
---|
| 296 | #Check out from CVS host |
---|
| 297 | s = 'ssh -X %s@%s "cd %s;cvs -d %s checkout %s"'\ |
---|
| 298 | %(username, cvs_client, sandpit, CVSROOT, arg) |
---|
| 299 | print '---------- CVS OUTPUT -------------' |
---|
| 300 | run(s) |
---|
| 301 | |
---|
| 302 | #Download from CVS client |
---|
| 303 | download(arg) |
---|
| 304 | |
---|
| 305 | else: |
---|
| 306 | print 'Usage' |
---|
| 307 | print ''' |
---|
| 308 | rcvs checkout repository (checkout repository from cvs client) |
---|
| 309 | |
---|
| 310 | rcvs add [files...] (add named files to repository) |
---|
| 311 | |
---|
| 312 | rcvs update [files...] (update named files from cvs server) |
---|
| 313 | |
---|
| 314 | rcvs com -m "msg" [files...] (Commit changes with log message) |
---|
| 315 | |
---|
| 316 | rcvs log [files...] (List log history for files) |
---|
| 317 | |
---|
| 318 | rcvs diff [files...] (List diffs for files) |
---|
| 319 | |
---|
| 320 | rcvs annotate [files...] (List files with cvs annotations) |
---|
| 321 | |
---|
| 322 | rcvs download repository (download repository from cvs client)''' |
---|
| 323 | |
---|