git-cipher 0.1 → 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|