Commit 78569137d203163f459e5f965f27ee9e404e151c
1 parent
9eb8665e
Added directory expansion for cwd, home and gitroot. Fixes #5
Showing
1 changed file
with
61 additions
and
28 deletions
blimp.nim
... | ... | @@ -16,6 +16,7 @@ import md5, os, osproc, parseopt2, strutils, parsecfg, streams, lapp, subexes |
16 | 16 | # <homedir>/blimpStore/<originalfilename>-<md5sum> |
17 | 17 | # |
18 | 18 | # Configuration is in these locations in order: |
19 | +# | |
19 | 20 | # ./.blimp.conf |
20 | 21 | # <gitroot>/.blimp.conf |
21 | 22 | # ~/blimpstore/.blimp.conf |
... | ... | @@ -29,23 +30,57 @@ const |
29 | 30 | |
30 | 31 | var |
31 | 32 | blimpStore, remoteBlimpStore, uploadCommandFormat, downloadCommandFormat, deleteCommandFormat, rsyncPassword: string = nil |
33 | + homeDir, currentDir, gitRootDir: string | |
32 | 34 | verbose: bool |
33 | 35 | |
34 | 36 | let |
35 | 37 | defaultConfig = """ |
36 | 38 | [rsync] |
37 | -# Set this to your remote rsync daemon area | |
39 | +# Set your local blimpstore directory. | |
40 | +# Example: | |
41 | +# # Place it inside the git clone | |
42 | +# blimpstore = "%gitroot%/.git/blimpstore" | |
43 | +# # Place it in current working directory (not very useful) | |
44 | +# blimpstore = "%cwd%/blimpstore" | |
45 | +# | |
46 | +# Default: | |
47 | +# # Place it in the users home directory | |
48 | +# blimpstore = "%home%/blimpstore" | |
49 | + | |
50 | +# Set this to your remote rsync location | |
38 | 51 | remote = "blimpuser@some-rsync-server.com::blimpstore" |
52 | +# Set this to your rsync password | |
39 | 53 | password = "some-good-rsync-password-for-blimpuser" |
40 | 54 | |
41 | 55 | # The following three formats should not need editing |
42 | -# $1 is filename, $2 is remote and $3 is the local blimpstore | |
56 | +# $1 is the blimp filename, $2 is remote location and $3 is | |
57 | +# the local blimpstore directory. | |
58 | +# NOTE: The password-file will be created by blimp on every command. | |
43 | 59 | upload = "rsync --password-file $3/.blimp.pass -avzP $3/$1 $2/" |
44 | 60 | download = "rsync --password-file $3/.blimp.pass -avzP $2/$1 $3/" |
45 | -# This deletes a single file from destination, that is already deleted in source | |
61 | +# This deletes a single file from destination, that is already deleted in source. Yeah... insane! But it works. | |
46 | 62 | delete = "rsync --password-file $3/.blimp.pass -dv --delete --existing --ignore-existing --include '$1' --exclude '*' $3/ $2" |
47 | 63 | """ |
48 | 64 | |
65 | +# Find git root dir or nil | |
66 | +proc gitRoot(): string = | |
67 | + try: | |
68 | + let tup = execCmdEx("git rev-parse --show-toplevel") | |
69 | + if tup[1] == 0: | |
70 | + result = strip(tup[0]) | |
71 | + else: | |
72 | + result = nil | |
73 | + except: | |
74 | + result = nil | |
75 | + | |
76 | +# Simple expansion of %home%, %cwd% and %gitroot% | |
77 | +proc expandDirs(templ: string): string = | |
78 | + result = templ.replace("%home%", homeDir) | |
79 | + result = result.replace("%cwd%", currentDir) | |
80 | + if result.contains("%gitroot%"): | |
81 | + if gitRootDir.isNil: quit("Not in a git clone, can not expand %gitroot% in '" & templ & "'") | |
82 | + result = result.replace("%gitroot%", gitRootDir) | |
83 | + | |
49 | 84 | # Load a blimp.conf file |
50 | 85 | proc parseConfFile(filename: string) = |
51 | 86 | var f = newFileStream(filename, fmRead) |
... | ... | @@ -64,17 +99,17 @@ proc parseConfFile(filename: string) = |
64 | 99 | of cfgKeyValuePair: |
65 | 100 | case e.key |
66 | 101 | of "blimpstore": |
67 | - if blimpStore.isNil: blimpStore = e.value | |
102 | + if blimpStore.isNil: blimpStore = expandDirs(e.value) | |
68 | 103 | of "remote": |
69 | - if remoteBlimpStore.isNil: remoteBlimpStore = e.value | |
104 | + if remoteBlimpStore.isNil: remoteBlimpStore = expandDirs(e.value) | |
70 | 105 | of "password": |
71 | 106 | if rsyncPassword.isNil: rsyncPassword = e.value |
72 | 107 | of "upload": |
73 | - if uploadCommandFormat.isNil: uploadCommandFormat = e.value | |
108 | + if uploadCommandFormat.isNil: uploadCommandFormat = expandDirs(e.value) | |
74 | 109 | of "download": |
75 | - if downloadCommandFormat.isNil: downloadCommandFormat = e.value | |
110 | + if downloadCommandFormat.isNil: downloadCommandFormat = expandDirs(e.value) | |
76 | 111 | of "delete": |
77 | - if deleteCommandFormat.isNil: deleteCommandFormat = e.value | |
112 | + if deleteCommandFormat.isNil: deleteCommandFormat = expandDirs(e.value) | |
78 | 113 | else: |
79 | 114 | quit("Unknown configuration: " & e.key) |
80 | 115 | of cfgOption: |
... | ... | @@ -90,9 +125,10 @@ proc run(cmd: string): auto = |
90 | 125 | |
91 | 126 | # Every rsync command, make sure we have a password file |
92 | 127 | proc rsyncRun(cmd: string): auto = |
93 | - writeFile(blimpStore / ".blimp.pass", rsyncPassword) | |
94 | - if execCmd("chmod 600 " & blimpStore / ".blimp.pass") != 0: | |
95 | - quit("Failed to chmod 600 " & blimpStore / ".blimp.pass") | |
128 | + if not rsyncPassword.isNil: | |
129 | + writeFile(blimpStore / ".blimp.pass", rsyncPassword) | |
130 | + if execCmd("chmod 600 " & blimpStore / ".blimp.pass") != 0: | |
131 | + quit("Failed to chmod 600 " & blimpStore / ".blimp.pass") | |
96 | 132 | run(cmd) |
97 | 133 | |
98 | 134 | # Upload a file to the remote master blimpStore |
... | ... | @@ -192,16 +228,6 @@ proc remove(filename: string) = |
192 | 228 | deleteFromBlimpStore(blimpfilename, filename) |
193 | 229 | echo("\t" & filename & " content removed from blimpstore locally and remotely.") |
194 | 230 | |
195 | -# Find git root dir or nil | |
196 | -proc gitRoot(): string = | |
197 | - try: | |
198 | - let tup = execCmdEx("git rev-parse --show-toplevel") | |
199 | - if tup[1] == 0: | |
200 | - result = strip(tup[0]) | |
201 | - else: | |
202 | - result = nil | |
203 | - except: | |
204 | - result = nil | |
205 | 231 | |
206 | 232 | proc setupBlimpStore() = |
207 | 233 | try: |
... | ... | @@ -216,6 +242,9 @@ proc setupBlimpStore() = |
216 | 242 | except: |
217 | 243 | quit("Could not create .blimp.conf config file in " & blimpStore & " directory.", 1) |
218 | 244 | |
245 | +proc `$`(x: string): string = | |
246 | + if x.isNil: "nil" else: x | |
247 | + | |
219 | 248 | proc dumpConfig() = |
220 | 249 | echo "\nDump of configuration:" |
221 | 250 | echo "\tblimpStore: " & blimpStore |
... | ... | @@ -223,7 +252,7 @@ proc dumpConfig() = |
223 | 252 | echo "\tuploadCommandFormat: " & uploadCommandFormat |
224 | 253 | echo "\tdownloadCommandFormat: " & downloadCommandFormat |
225 | 254 | echo "\tdeleteCommandFormat: " & deleteCommandFormat |
226 | - echo "\trsyncPassword: " & rsyncPassword | |
255 | + echo "\trsyncPassword: " & $rsyncPassword | |
227 | 256 | echo "\n" |
228 | 257 | |
229 | 258 | let help = """ |
... | ... | @@ -254,23 +283,28 @@ let help = """ |
254 | 283 | """ |
255 | 284 | |
256 | 285 | ################################ main ##################################### |
286 | +# Set some dirs | |
287 | +homeDir = getHomeDir() | |
288 | +homeDir = homeDir[0.. -2] # Not sure why it keeps a trailing "/" on Linux | |
289 | +currentDir = getCurrentDir() | |
290 | +gitRootDir = gitRoot() | |
257 | 291 | |
258 | 292 | # Using lapp to get args, on parsing failure this will show usage automatically |
259 | 293 | var args = parse(help) |
260 | 294 | verbose = args["verbose"].asBool |
261 | 295 | |
262 | 296 | # Parse configuration files, may shadow and override each other |
263 | -parseConfFile(getCurrentDir() / ".blimp.conf") | |
264 | -if not gitRoot().isNil: | |
265 | - parseConfFile(gitRoot() / ".blimp.conf") | |
297 | +parseConfFile(currentDir / ".blimp.conf") | |
298 | +if not gitRootDir.isNil: | |
299 | + parseConfFile(gitRootDir / ".blimp.conf") | |
266 | 300 | |
267 | 301 | # If we haven't gotten a blimpstore yet, we set a default one |
268 | 302 | if blimpStore.isNil: |
269 | - blimpStore = getHomeDir() / "blimpstore" | |
303 | + blimpStore = homeDir / "blimpstore" | |
270 | 304 | |
271 | 305 | if existsDir(blimpStore): |
272 | 306 | parseConfFile(blimpStore / ".blimp.conf") |
273 | -parseConfFile(getHomeDir() / ".blimp.conf") | |
307 | +parseConfFile(homeDir / ".blimp.conf") | |
274 | 308 | |
275 | 309 | if verbose: dumpConfig() |
276 | 310 | |
... | ... | @@ -285,7 +319,6 @@ let filenames = args["filenames"].asSeq |
285 | 319 | setupBlimpStore() |
286 | 320 | |
287 | 321 | |
288 | - | |
289 | 322 | # Do the deed |
290 | 323 | if command == "d" or command == "deflate": |
291 | 324 | for fn in filenames: | ... | ... |