db95b901
Göran Krampe
Various fixes, mo...
|
1
|
import md5, os, osproc, parseopt2, strutils, parsecfg, streams, lapp
|
74272cdb
Göran Krampe
First commit
|
2
|
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
3
|
# blimp is a little utility program for handling large files
|
74272cdb
Göran Krampe
First commit
|
4
|
# in git repositories. Its inspired by git-fat and s3annex
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
5
6
|
# but doesn't rely on S3 for storage, is a single binary without
# need for Python, and has less features than git-fat. So far.
|
74272cdb
Göran Krampe
First commit
|
7
|
#
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
8
9
10
11
|
# Manual use:
#
# Use "blimp d mybigfile" to deflate it before commit.
# Use "blimp i mybigfile" to inflate it back to original size.
|
74272cdb
Göran Krampe
First commit
|
12
13
14
15
|
#
# When deflated the file only has an md5sum string inside it.
#
# The file is copied over into:
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
16
17
18
19
20
|
# <homedir>/blimpStore/<originalfilename>-<md5sum>
#
# Configuration is in:
# <gitroot>/.blimp.conf
# ~/blimpstore/.blimp.conf
|
74272cdb
Göran Krampe
First commit
|
21
|
|
db95b901
Göran Krampe
Various fixes, mo...
|
22
23
|
var blimpStore, remoteBlimpStore: string = nil
var verbose: bool
|
74272cdb
Göran Krampe
First commit
|
24
25
|
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
26
|
# Load blimp.conf file, overkill for now but...
|
74272cdb
Göran Krampe
First commit
|
27
|
proc parseConfFile(filename: string) =
|
74272cdb
Göran Krampe
First commit
|
28
29
30
31
32
33
34
35
36
37
38
39
40
|
var f = newFileStream(filename, fmRead)
if f != nil:
var p: CfgParser
open(p, f, filename)
while true:
var e = next(p)
case e.kind
of cfgEof:
break
of cfgSectionStart:
continue # Ignore
of cfgKeyValuePair:
if e.key == "remote":
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
41
|
remoteBlimpStore = e.value
|
74272cdb
Göran Krampe
First commit
|
42
43
44
45
46
47
48
49
|
else:
quit("Unknown configuration: " & e.key)
of cfgOption:
quit("Unknown configuration: " & e.key)
of cfgError:
quit("Parsing " & filename & ": " & e.msg)
close(p)
|
db95b901
Göran Krampe
Various fixes, mo...
|
50
51
52
53
|
# Trivial helper to enable verbose
proc run(cmd: string): auto =
if verbose: echo(cmd)
execCmd(cmd)
|
74272cdb
Göran Krampe
First commit
|
54
|
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
55
56
57
58
|
# Upload a file to the remote master blimpStore
proc uploadFile(blimpFilename: string) =
if remoteBlimpStore.isNil:
echo("Remote blimpstore not set in configuration file, not uploading content:\n\t" & blimpFilename)
|
74272cdb
Göran Krampe
First commit
|
59
|
return
|
db95b901
Göran Krampe
Various fixes, mo...
|
60
|
let errorCode = run("rsync -a " & blimpStore / blimpFilename & " " & remoteBlimpStore)
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
61
|
if errorCode != 0: quit("Something went wrong uploading content to " & remoteBlimpStore, 2)
|
74272cdb
Göran Krampe
First commit
|
62
|
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
63
64
65
66
|
# Download a file to the remote master blimpStore
proc downloadFile(blimpFilename: string) =
if remoteBlimpStore.isNil:
quit("Remote blimpstore not set in configuration file, can not download content:\n\t" & blimpFilename)
|
db95b901
Göran Krampe
Various fixes, mo...
|
67
|
let errorCode = run("rsync -a " & remoteBlimpStore / blimpFilename & " " & blimpStore / "")
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
if errorCode != 0: quit("Something went wrong downloading " & blimpFilename & " from " & remoteBlimpStore, 3)
# Copy content to blimpStore, no upload yet.
proc copyToBlimpStore(filename, blimpFilename: string) =
if not existsFile(blimpStore / blimpFilename):
copyFile(filename, blimpStore / blimpFilename)
uploadFile(blimpFilename)
# Copy content from blimpStore, and downloading first if needed
proc copyFromblimpStore(blimpFilename, filename: string) =
if not existsFile(blimpStore / blimpFilename):
downloadFile(blimpFilename)
copyFile(blimpStore / blimpFilename, filename)
|
74272cdb
Göran Krampe
First commit
|
82
83
|
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
84
|
# Copy original file to blimpStore and replace with hash stub in git.
|
74272cdb
Göran Krampe
First commit
|
85
|
proc deflate(filename: string) =
|
db95b901
Göran Krampe
Various fixes, mo...
|
86
87
88
89
90
|
var content: string
try:
content = readFile(filename)
except:
quit("Failed opening file: " & filename, 1)
|
74272cdb
Göran Krampe
First commit
|
91
92
93
|
if content[0..4] == "hash:":
quit("File is already deflated, ignored.", 5)
let hash = getMD5(content)
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
94
95
96
|
let blimpFilename = filename & "-" & hash
copyToBlimpStore(filename, blimpFilename)
writeFile(filename, "hash:" & blimpFilename)
|
db95b901
Göran Krampe
Various fixes, mo...
|
97
98
|
echo("\t" & filename & " deflated.")
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
99
|
# Parse out hash from hash stub and copy back original content from blimpStore.
|
74272cdb
Göran Krampe
First commit
|
100
101
102
|
proc inflate(filename: string) =
var hashfile: File
if not open(hashfile, filename):
|
db95b901
Göran Krampe
Various fixes, mo...
|
103
|
quit("Failed opening file: " & filename, 4)
|
74272cdb
Göran Krampe
First commit
|
104
105
|
let hashline = split(string(readLine(hashfile)), {':'})
if hashline[0] == "hash":
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
106
|
let blimpfilename = hashline[1]
|
74272cdb
Göran Krampe
First commit
|
107
|
#removeFile(filename)
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
108
|
copyFromblimpStore(blimpfilename, filename)
|
74272cdb
Göran Krampe
First commit
|
109
|
else:
|
db95b901
Göran Krampe
Various fixes, mo...
|
110
111
|
quit("\t" & filename & " is not deflated.", 5)
echo("\t" & filename & " inflated.")
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
112
113
114
115
116
117
118
119
120
121
122
|
# Find git root dir or fall back on current dir
proc gitRoot(): string =
try:
let tup = execCmdEx("git rev-parse --show-toplevel")
if tup[1] == 0:
result = tup[0]
else:
result = getCurrentDir()
except:
result = getCurrentDir()
|
74272cdb
Göran Krampe
First commit
|
123
|
|
db95b901
Göran Krampe
Various fixes, mo...
|
124
125
126
127
128
129
130
|
let help = """
blimp [options] <command> <filenames...>
-v,--verbose Verbosity
<command> (string) (i)nflate or (d)eflate
<filenames> (string...) One or more filepaths to inflate/deflate
"""
|
74272cdb
Göran Krampe
First commit
|
131
132
|
################################ main #####################################
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
133
134
|
# Hardwired to "blimpstore" directory in home dir.
blimpStore = getHomeDir() / "blimpstore"
|
74272cdb
Göran Krampe
First commit
|
135
136
137
|
# Make sure we have the dir, or create it.
try:
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
138
|
if not existsDir(blimpStore): createDir(blimpStore)
|
74272cdb
Göran Krampe
First commit
|
139
|
except:
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
140
|
quit("Could not create " & blimpStore & " directory.", 1)
|
74272cdb
Göran Krampe
First commit
|
141
142
|
|
5fc367ad
Göran Krampe
Renamed to blimp,...
|
143
144
145
|
# Parse configuration files if they exist
parseConfFile(gitRoot() / ".blimp.conf")
parseConfFile(blimpStore / ".blimp.conf")
|
74272cdb
Göran Krampe
First commit
|
146
|
|
db95b901
Göran Krampe
Various fixes, mo...
|
147
148
149
150
151
|
# Using lapp to get args
let args = parse(help)
let command = args["command"].asString
let filenames = args["filenames"].asSeq
verbose = args["verbose"].asBool
|
74272cdb
Göran Krampe
First commit
|
152
153
154
|
# Do the deed
if command == "d" or command == "deflate":
|
db95b901
Göran Krampe
Various fixes, mo...
|
155
156
|
for fn in filenames:
deflate(fn.asString)
|
74272cdb
Göran Krampe
First commit
|
157
|
elif command == "i" or command == "inflate":
|
db95b901
Göran Krampe
Various fixes, mo...
|
158
159
|
for fn in filenames:
inflate(fn.asString)
|
74272cdb
Göran Krampe
First commit
|
160
161
162
163
164
|
else:
quit("Unknown command, only (d)eflate or (i)inflate are valid.", 6)
# All good
quit(0)
|