git-cipher 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/git-cipher +113 -19
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d52bb65c34660958a91e70fef43d596610bede9
|
4
|
+
data.tar.gz: 7d83c6b13437a4fa8c1d166b76fda86abdf9a990
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53dec9da0d8e7bed2874793c25bde8e9fad254059bdccee796dec7b131a7191a6a863ced6873e797007167236de4a5f25dfc562b33e01a7506d98da32d7872cb
|
7
|
+
data.tar.gz: e1c65440edaeb32687e7b124f6c497bd8e9413f4ef7c7f92a23d55d13ab29691a820eed6918ca819f6273e4308fb8c1a4d9cabd5939b4661da25ee785766e2f2
|
data/bin/git-cipher
CHANGED
@@ -4,13 +4,14 @@
|
|
4
4
|
require 'fileutils'
|
5
5
|
require 'pathname'
|
6
6
|
require 'shellwords'
|
7
|
+
require 'tempfile'
|
7
8
|
|
8
9
|
class Cipher
|
9
10
|
EXTENSION = 'encrypted'
|
10
11
|
DEFAULT_GPG_USER = 'greg@hurrell.net'
|
11
12
|
DEFAULT_GPG_PRESET_COMMAND = '/usr/local/opt/gpg-agent/libexec/gpg-preset-passphrase'
|
12
13
|
VALID_OPTIONS = %w[force help]
|
13
|
-
VALID_SUBCOMMANDS = %w[decrypt encrypt help preset forget]
|
14
|
+
VALID_SUBCOMMANDS = %w[decrypt encrypt help log preset forget]
|
14
15
|
|
15
16
|
def run
|
16
17
|
send @subcommand
|
@@ -69,14 +70,7 @@ private
|
|
69
70
|
end
|
70
71
|
|
71
72
|
def decrypt!(file)
|
72
|
-
|
73
|
-
die <<-MSG
|
74
|
-
GPG_AGENT_INFO not present in the environment.
|
75
|
-
Try running:
|
76
|
-
eval $(gpg-agent --daemon)
|
77
|
-
#{command_name} preset
|
78
|
-
MSG
|
79
|
-
end
|
73
|
+
require_agent
|
80
74
|
|
81
75
|
pathname = Pathname.new(file)
|
82
76
|
basename = pathname.basename.to_s
|
@@ -104,16 +98,7 @@ private
|
|
104
98
|
puts red('[warning: plain-text newer than ciphertext; skipping]')
|
105
99
|
else
|
106
100
|
print green('[decrypting ...')
|
107
|
-
|
108
|
-
#{escape command_path('gpg')}
|
109
|
-
-q
|
110
|
-
--yes
|
111
|
-
--batch
|
112
|
-
--no-tty
|
113
|
-
--use-agent
|
114
|
-
-o #{escape outfile}
|
115
|
-
-d #{escape file}
|
116
|
-
})
|
101
|
+
gpg_decrypt(file, outfile)
|
117
102
|
if $?.success?
|
118
103
|
puts green(' done]')
|
119
104
|
|
@@ -219,6 +204,19 @@ private
|
|
219
204
|
puts
|
220
205
|
end
|
221
206
|
|
207
|
+
def gpg_decrypt(file, outfile)
|
208
|
+
execute(%{
|
209
|
+
#{escape command_path('gpg')}
|
210
|
+
-q
|
211
|
+
--yes
|
212
|
+
--batch
|
213
|
+
--no-tty
|
214
|
+
--use-agent
|
215
|
+
-o #{escape outfile}
|
216
|
+
-d #{escape file}
|
217
|
+
})
|
218
|
+
end
|
219
|
+
|
222
220
|
def gpg_preset_command
|
223
221
|
ENV['GPG_PRESET_COMMAND'] || get_config('presetcommand') || DEFAULT_GPG_PRESET_COMMAND
|
224
222
|
end
|
@@ -248,6 +246,64 @@ private
|
|
248
246
|
"\e[2K\e[0G"
|
249
247
|
end
|
250
248
|
|
249
|
+
def log
|
250
|
+
if @files.empty?
|
251
|
+
# TODO: would be nice to interleave these instead of doing them serially.
|
252
|
+
puts 'No explicit paths supplied: logging all matching files'
|
253
|
+
Dir["**/.*.#{EXTENSION}"].each { |file| log!(file) }
|
254
|
+
else
|
255
|
+
@files.each { |file| log!(file) }
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def log!(file)
|
260
|
+
require_agent
|
261
|
+
|
262
|
+
commits = execute(%{
|
263
|
+
#{escape command_path('git')} log
|
264
|
+
--pretty=format:%H -- #{escape file}
|
265
|
+
}).split
|
266
|
+
|
267
|
+
commits.each do |commit|
|
268
|
+
files = []
|
269
|
+
begin
|
270
|
+
# Get plaintext "post" image.
|
271
|
+
files.push(post = temp_write(show(file, commit)))
|
272
|
+
files.push(
|
273
|
+
post_plaintext = temp_write(gpg_decrypt(post.path, '-'))
|
274
|
+
)
|
275
|
+
|
276
|
+
# Get plaintext "pre" image.
|
277
|
+
files.push(pre = temp_write(show(file, "#{commit}~")))
|
278
|
+
files.push(pre_plaintext = temp_write(
|
279
|
+
pre.size.zero? ? '' : gpg_decrypt(pre.path, '-')
|
280
|
+
))
|
281
|
+
|
282
|
+
# Print commit message.
|
283
|
+
puts execute(%{
|
284
|
+
#{escape command_path('git')} --no-pager log
|
285
|
+
--color=always -1 #{commit}
|
286
|
+
})
|
287
|
+
puts
|
288
|
+
|
289
|
+
# Print pre-to-post diff.
|
290
|
+
puts execute(%{
|
291
|
+
#{escape command_path('git')} --no-pager diff
|
292
|
+
--color=always
|
293
|
+
#{escape pre_plaintext.path}
|
294
|
+
#{escape post_plaintext.path}
|
295
|
+
})
|
296
|
+
puts
|
297
|
+
|
298
|
+
ensure
|
299
|
+
files.each do |tempfile|
|
300
|
+
tempfile.close
|
301
|
+
tempfile.unlink
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
251
307
|
def normalize_option(option)
|
252
308
|
normal = option.dup
|
253
309
|
|
@@ -295,12 +351,40 @@ private
|
|
295
351
|
colorize(string, 31)
|
296
352
|
end
|
297
353
|
|
354
|
+
def require_agent
|
355
|
+
unless ENV['GPG_AGENT_INFO']
|
356
|
+
die <<-MSG
|
357
|
+
GPG_AGENT_INFO not present in the environment.
|
358
|
+
Try running this before retrying `#{command_name} #{@subcommand}`:
|
359
|
+
eval $(gpg-agent --daemon)
|
360
|
+
#{command_name} preset
|
361
|
+
MSG
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
def show(file, commit)
|
366
|
+
# Redirect stderr to /dev/null because the file might not have existed prior
|
367
|
+
# to this commit.
|
368
|
+
execute(%{
|
369
|
+
#{escape command_path('git')} show
|
370
|
+
#{commit}:#{escape file} 2> /dev/null
|
371
|
+
})
|
372
|
+
end
|
373
|
+
|
298
374
|
def strip_heredoc(doc)
|
299
375
|
# based on method of same name from Rails
|
300
376
|
indent = doc.scan(/^[ \t]*(?=\S)/).map(&:size).min || 0
|
301
377
|
doc.gsub(/^[ \t]{#{indent}}/, '')
|
302
378
|
end
|
303
379
|
|
380
|
+
def temp_write(contents)
|
381
|
+
file = Tempfile.new('git-cipher-')
|
382
|
+
file.chmod(0600)
|
383
|
+
file.write(contents)
|
384
|
+
file.flush
|
385
|
+
file
|
386
|
+
end
|
387
|
+
|
304
388
|
# Print usage information and exit.
|
305
389
|
def usage(subcommand)
|
306
390
|
case subcommand
|
@@ -354,6 +438,15 @@ private
|
|
354
438
|
|
355
439
|
#{command_name} forget
|
356
440
|
USAGE
|
441
|
+
when 'log'
|
442
|
+
puts strip_heredoc(<<-USAGE)
|
443
|
+
#{command_name} log FILE
|
444
|
+
|
445
|
+
Shows the log message and decrypted diff for FILE
|
446
|
+
(analogous to `git log -p -- FILE`).
|
447
|
+
|
448
|
+
#{command_name} log foo
|
449
|
+
USAGE
|
357
450
|
when 'preset'
|
358
451
|
puts strip_heredoc(<<-USAGE)
|
359
452
|
#{command_name} preset
|
@@ -369,6 +462,7 @@ private
|
|
369
462
|
#{command_name} decrypt
|
370
463
|
#{command_name} encrypt
|
371
464
|
#{command_name} forget
|
465
|
+
#{command_name} log
|
372
466
|
#{command_name} preset
|
373
467
|
USAGE
|
374
468
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-cipher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg Hurrell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: "\n Provides a convenient workflow for working with encrypted files
|
14
14
|
in a public\n Git repo. Delegates the underlying work of encryption/decryption
|