safe 0.4 → 0.5
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.
- data/README +48 -2
- data/Rakefile +1 -1
- data/Release-Notes.txt +6 -0
- data/bin/safe +22 -13
- data/lib/safediff.rb +80 -0
- data/lib/safeentry.rb +11 -3
- data/lib/safeutils.rb +64 -0
- data/test/tc_safediff.rb +52 -0
- data/test/tc_safeutils.rb +56 -0
- metadata +4 -2
data/README
CHANGED
@@ -4,6 +4,34 @@ user IDs and passwords using a single password as the master key. It stores the
|
|
4
4
|
master key as a hash (SHA2), and uses it to encrypt the rest of the data using
|
5
5
|
Blowfish.
|
6
6
|
|
7
|
+
== A Note About Moving from 0.3 to 0.4 ==
|
8
|
+
The format of the file changed slightly. Specifically, the salt and hash values
|
9
|
+
were changed to be attributes of the root safe element. You must edit your
|
10
|
+
.safe.xml file accordingly.
|
11
|
+
|
12
|
+
Example:
|
13
|
+
0.3 version:
|
14
|
+
<safe>
|
15
|
+
<salt>
|
16
|
+
foo
|
17
|
+
</salt>
|
18
|
+
<hash>
|
19
|
+
bar
|
20
|
+
</hash>
|
21
|
+
<entries>
|
22
|
+
...
|
23
|
+
</entries>
|
24
|
+
</salt>
|
25
|
+
|
26
|
+
0.4 version:
|
27
|
+
<safe salt="foo" hash="bar">
|
28
|
+
<entries>
|
29
|
+
...
|
30
|
+
</entries>
|
31
|
+
</salt>
|
32
|
+
|
33
|
+
This is a one-time operation.
|
34
|
+
|
7
35
|
== License ==
|
8
36
|
Safe is licensed under the BSD License. Copyright (c) 2007, Rob Warner
|
9
37
|
|
@@ -37,7 +65,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
37
65
|
To install safe, you must have Ruby and Ruby Gems installed. From the command
|
38
66
|
line, type:
|
39
67
|
|
40
|
-
gem install safe
|
68
|
+
gem install safe
|
41
69
|
|
42
70
|
safe depends on two gems:
|
43
71
|
|
@@ -59,6 +87,7 @@ Windows:
|
|
59
87
|
0.2 -- August 19, 2007
|
60
88
|
0.3 -- September 7, 2007
|
61
89
|
0.4 -- April 4, 2008
|
90
|
+
0.5 -- April 6, 2008
|
62
91
|
|
63
92
|
See Release-Notes.txt for more information
|
64
93
|
|
@@ -107,7 +136,9 @@ Options:
|
|
107
136
|
-l, --list NAME List an entry
|
108
137
|
-v, --version Print version
|
109
138
|
-p, --password Change password
|
110
|
-
|
139
|
+
-f, --diff DIR Diff against password file in directory DIR
|
140
|
+
-m, --merge DIR Merge with password file in directory DIR
|
141
|
+
|
111
142
|
For example, to add an entry to your password file for Rubyforge.org, you type:
|
112
143
|
|
113
144
|
safe -a Rubyforge.org
|
@@ -147,6 +178,21 @@ You will be prompted for your master password, and then your Rubyforge.org
|
|
147
178
|
password is irretrievably deleted. You will not be asked to confirm the
|
148
179
|
deletion.
|
149
180
|
|
181
|
+
== Diff and Merge ==
|
182
|
+
Diffing and merging deviates slightly from diffing and merging other types of
|
183
|
+
files, since typically users want a union of the files without deleting any
|
184
|
+
entries. Consequently, instead of Add/Delete/Change, the output of diff will
|
185
|
+
indicate Master/Other/Change, meaning the entry is only in the Master copy
|
186
|
+
(the one in the directory pointed to by SAFE_DIR), the Other copy (the one in
|
187
|
+
the directory passed on the command line), or is in both but has been Changed,
|
188
|
+
respectively.
|
189
|
+
|
190
|
+
Merge does two things:
|
191
|
+
1) Adds all entries from the Other copy that don't exist in the Master copy
|
192
|
+
to the Master copy
|
193
|
+
2) Interactively performs requested changes to changed entries on the Master
|
194
|
+
copy
|
195
|
+
|
150
196
|
== Backups ==
|
151
197
|
Please back up your .safe.xml file! See License section for disclaimer
|
152
198
|
information.
|
data/Rakefile
CHANGED
@@ -7,7 +7,7 @@ gem_spec = Gem::Specification.new do |spec|
|
|
7
7
|
spec.summary = 'A command-line password storage program'
|
8
8
|
spec.description = %{safe safely stores all your user IDs and passwords,
|
9
9
|
encrypted by a password of your choosing.}
|
10
|
-
spec.version = '0.
|
10
|
+
spec.version = '0.5'
|
11
11
|
|
12
12
|
# Author information
|
13
13
|
spec.author = 'Rob Warner'
|
data/Release-Notes.txt
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
Safe Release Notes
|
2
2
|
------------------
|
3
|
+
0.5 (April 6, 2008)
|
4
|
+
-------------------
|
5
|
+
[FIXED] Version number in help output corrected
|
6
|
+
[NEW] Added diff and merge capabilities
|
7
|
+
[CHANGE] Incorrect password no longer displays stack trace
|
8
|
+
|
3
9
|
0.4 (April 4, 2008)
|
4
10
|
-------------------
|
5
11
|
[FIXED] Passwords stopped authenticating (change in REXML perhaps?--whitespace returned in salt and hash), so moved salt
|
data/bin/safe
CHANGED
@@ -41,7 +41,7 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'safeutils')
|
|
41
41
|
# TODO support list <NAME> without -l flag
|
42
42
|
|
43
43
|
class Safe
|
44
|
-
SAFE_VERSION = '0.
|
44
|
+
SAFE_VERSION = '0.5'
|
45
45
|
|
46
46
|
# Gets the command line
|
47
47
|
def self.get_command_line
|
@@ -76,6 +76,14 @@ class Safe
|
|
76
76
|
opts.on('-p', '--password', 'Change password') do
|
77
77
|
options[:action] = 'password'
|
78
78
|
end
|
79
|
+
opts.on('-f', '--diff DIR', 'Diff against password file in directory DIR') do |val|
|
80
|
+
options[:name] = val
|
81
|
+
options[:action] = 'diff'
|
82
|
+
end
|
83
|
+
opts.on('-m', '--merge DIR', 'Merge with password file in directory DIR') do |val|
|
84
|
+
options[:name] = val
|
85
|
+
options[:action] = 'merge'
|
86
|
+
end
|
79
87
|
opts.parse! rescue abort [$!.message, opts].join("\n")
|
80
88
|
options
|
81
89
|
end
|
@@ -88,21 +96,22 @@ class Safe
|
|
88
96
|
else
|
89
97
|
begin
|
90
98
|
dir = SafeUtils::get_safe_dir
|
99
|
+
file = SafeUtils::get_safe_file(dir)
|
100
|
+
|
101
|
+
# Perform the requested action
|
102
|
+
case options[:action]
|
103
|
+
when 'list': file.list(options[:name])
|
104
|
+
when 'add': file.add(options[:name])
|
105
|
+
when 'delete': file.delete(options[:name])
|
106
|
+
when 'count': puts file.count
|
107
|
+
when 'password': file.change_password
|
108
|
+
when 'import': SafeUtils::import(file, options[:name])
|
109
|
+
when 'diff': SafeUtils::diff(file, options[:name])
|
110
|
+
when 'merge': SafeUtils::merge(file, options[:name])
|
111
|
+
end
|
91
112
|
rescue
|
92
113
|
abort $!.message
|
93
114
|
end
|
94
|
-
password = SafeUtils::get_password
|
95
|
-
file = SafeFile.new(password, dir)
|
96
|
-
|
97
|
-
# Perform the requested action
|
98
|
-
case options[:action]
|
99
|
-
when 'list': file.list(options[:name])
|
100
|
-
when 'add': file.add(options[:name])
|
101
|
-
when 'delete': file.delete(options[:name])
|
102
|
-
when 'count': puts file.count
|
103
|
-
when 'password': file.change_password
|
104
|
-
when 'import': SafeUtils::import(file, options[:name])
|
105
|
-
end
|
106
115
|
end
|
107
116
|
end
|
108
117
|
end
|
data/lib/safediff.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
########################################################################
|
2
|
+
# safediff.rb
|
3
|
+
# Copyright (c) 2007, Rob Warner
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are met:
|
9
|
+
#
|
10
|
+
# * Redistributions of source code must retain the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer.
|
12
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
# this list of conditions and the following disclaimer in the documentation
|
14
|
+
# and/or other materials provided with the distribution.
|
15
|
+
# * Neither the name of Rob Warner nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
20
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
21
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
22
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
23
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
24
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
25
|
+
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
26
|
+
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
27
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
28
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
29
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
########################################################################
|
31
|
+
|
32
|
+
##
|
33
|
+
# SafeDiff
|
34
|
+
# Contains a difference between two safe entries
|
35
|
+
##
|
36
|
+
class SafeDiff
|
37
|
+
attr_accessor :operation, :master, :other
|
38
|
+
|
39
|
+
MASTER = "m"
|
40
|
+
OTHER = "o"
|
41
|
+
CHANGE = "c"
|
42
|
+
|
43
|
+
def initialize(master, other)
|
44
|
+
self.master = master
|
45
|
+
self.other = other
|
46
|
+
compare
|
47
|
+
end
|
48
|
+
|
49
|
+
def compare
|
50
|
+
if self.master != nil && self.master.equals?(self.other)
|
51
|
+
raise "Entries are not different:\n#{self.master.to_s}\n#{self.other.to_s}"
|
52
|
+
elsif self.master != nil && self.other == nil
|
53
|
+
self.operation = MASTER
|
54
|
+
elsif self.master == nil && self.other != nil
|
55
|
+
self.operation = OTHER
|
56
|
+
else
|
57
|
+
self.operation = CHANGE
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
s = ""
|
63
|
+
s << self.operation
|
64
|
+
s << "\n"
|
65
|
+
if self.operation == MASTER || self.operation == CHANGE
|
66
|
+
s << "< "
|
67
|
+
s << self.master.to_s
|
68
|
+
s << "\n"
|
69
|
+
end
|
70
|
+
if self.operation == CHANGE
|
71
|
+
s << "---\n"
|
72
|
+
end
|
73
|
+
if self.operation == OTHER || self.operation == CHANGE
|
74
|
+
s << "> "
|
75
|
+
s << self.other.to_s
|
76
|
+
s << "\n"
|
77
|
+
end
|
78
|
+
s
|
79
|
+
end
|
80
|
+
end
|
data/lib/safeentry.rb
CHANGED
@@ -37,9 +37,9 @@ class SafeEntry
|
|
37
37
|
attr_accessor :name, :id, :password
|
38
38
|
|
39
39
|
def initialize(name, id, password)
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
self.name = name
|
41
|
+
self.id = id
|
42
|
+
self.password = password
|
43
43
|
end
|
44
44
|
|
45
45
|
def to_s
|
@@ -49,5 +49,13 @@ class SafeEntry
|
|
49
49
|
def <=>(other)
|
50
50
|
self.name.upcase <=> other.name.upcase
|
51
51
|
end
|
52
|
+
|
53
|
+
def equals? other
|
54
|
+
if other == nil
|
55
|
+
false
|
56
|
+
else
|
57
|
+
self.name == other.name && self.id == other.id && self.password == other.password
|
58
|
+
end
|
59
|
+
end
|
52
60
|
end
|
53
61
|
|
data/lib/safeutils.rb
CHANGED
@@ -28,6 +28,7 @@
|
|
28
28
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
29
29
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
30
|
########################################################################
|
31
|
+
require File.join(File.dirname(__FILE__), 'safediff')
|
31
32
|
require 'highline/import'
|
32
33
|
|
33
34
|
##
|
@@ -73,4 +74,67 @@ class SafeUtils
|
|
73
74
|
raise "Problem importing file #{import_file}"
|
74
75
|
end
|
75
76
|
end
|
77
|
+
|
78
|
+
def SafeUtils.get_safe_file(dir, prompt = 'Password: ')
|
79
|
+
password = SafeUtils::get_password(prompt)
|
80
|
+
SafeFile.new(password, dir)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Diffs two .safe.xml files
|
84
|
+
def SafeUtils.diff(safe_file, dir)
|
85
|
+
other_file = get_safe_file(dir, "#{dir} Password: ")
|
86
|
+
diffs = get_diffs(safe_file, other_file)
|
87
|
+
puts diffs
|
88
|
+
end
|
89
|
+
|
90
|
+
# Merges two .safe.xml files
|
91
|
+
def SafeUtils.merge(safe_file, dir)
|
92
|
+
other_file = get_safe_file(dir, "#{dir} Password: ")
|
93
|
+
diffs = get_diffs(safe_file, other_file)
|
94
|
+
do_merge safe_file, diffs
|
95
|
+
safe_file.save
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns the SafeDiff objects in an Array
|
99
|
+
def SafeUtils.get_diffs(safe_file, other_file)
|
100
|
+
diffs = Array.new
|
101
|
+
|
102
|
+
# Find master-only and changes
|
103
|
+
safe_file.entries.each_value do |entry|
|
104
|
+
if other_file.entries.has_key? entry.name
|
105
|
+
other_entry = other_file.entries[entry.name]
|
106
|
+
diffs << SafeDiff.new(entry, other_entry) unless entry.equals? other_entry
|
107
|
+
else
|
108
|
+
diffs << SafeDiff.new(entry, nil)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Find other-only
|
113
|
+
other_file.entries.each_value do |entry|
|
114
|
+
if !safe_file.entries.has_key? entry.name
|
115
|
+
diffs << SafeDiff.new(nil, entry)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
diffs
|
120
|
+
end
|
121
|
+
|
122
|
+
def SafeUtils.do_merge(safe_file, diffs, override_master = false)
|
123
|
+
diffs.each do |diff|
|
124
|
+
case diff.operation
|
125
|
+
when SafeDiff::MASTER: # Do nothing
|
126
|
+
when SafeDiff::OTHER: # Add to safe file
|
127
|
+
safe_file.insert(diff.other.name, diff.other.id, diff.other.password)
|
128
|
+
when SafeDiff::CHANGE: # Update safe file
|
129
|
+
if override_master || replace_master?(diff)
|
130
|
+
safe_file.insert(diff.other.name, diff.other.id, diff.other.password)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def SafeUtils.replace_master?(diff)
|
137
|
+
print "Replace:\n\t#{diff.master.to_s}\nWith:\n\t#{diff.other.to_s}\n?"
|
138
|
+
gets.chomp == 'y'
|
139
|
+
end
|
76
140
|
end
|
data/test/tc_safediff.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
########################################################################
|
2
|
+
# tc_safediff.rb
|
3
|
+
# Copyright (c) 2007 Rob Warner.
|
4
|
+
# All rights reserved. This program and the accompanying materials
|
5
|
+
# are made available under the terms of the Eclipse Public License v1.0
|
6
|
+
# which accompanies this distribution, and is available at
|
7
|
+
# http://www.eclipse.org/legal/epl-v10.html
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'safediff')
|
11
|
+
require 'test/unit'
|
12
|
+
|
13
|
+
class SafeDiffTest < Test::Unit::TestCase
|
14
|
+
def test_diff
|
15
|
+
e1 = SafeEntry.new('apple', 'baker', 'charlie')
|
16
|
+
e2 = SafeEntry.new('apple', 'baker', 'charlie')
|
17
|
+
e3 = SafeEntry.new('apple1', 'baker', 'charlie')
|
18
|
+
e4 = SafeEntry.new('apple', 'baker1', 'charlie')
|
19
|
+
e5 = SafeEntry.new('apple', 'baker', 'charlie1')
|
20
|
+
|
21
|
+
# Test two equal entries
|
22
|
+
begin
|
23
|
+
diff = SafeDiff.new e1, e2
|
24
|
+
rescue RuntimeError
|
25
|
+
assert_equal "Entries are not different:\n#{e1.to_s}\n#{e2.to_s}", $!.message
|
26
|
+
end
|
27
|
+
|
28
|
+
# Test an OTHER
|
29
|
+
diff = SafeDiff.new nil, e1
|
30
|
+
assert_equal diff.operation, SafeDiff::OTHER
|
31
|
+
assert_equal diff.to_s, "#{SafeDiff::OTHER}\n> #{e1.to_s}\n"
|
32
|
+
|
33
|
+
# Test a MASTER
|
34
|
+
diff = SafeDiff.new e1, nil
|
35
|
+
assert_equal diff.operation, SafeDiff::MASTER
|
36
|
+
assert_equal diff.to_s, "#{SafeDiff::MASTER}\n< #{e1.to_s}\n"
|
37
|
+
|
38
|
+
# Test a change
|
39
|
+
diff = SafeDiff.new e1, e3
|
40
|
+
assert_equal diff.operation, SafeDiff::CHANGE
|
41
|
+
assert_equal diff.to_s, "#{SafeDiff::CHANGE}\n< #{e1.to_s}\n---\n> #{e3.to_s}\n"
|
42
|
+
|
43
|
+
# Test various changes
|
44
|
+
diff = SafeDiff.new e1, e4
|
45
|
+
assert_equal diff.operation, SafeDiff::CHANGE
|
46
|
+
assert_equal diff.to_s, "#{SafeDiff::CHANGE}\n< #{e1.to_s}\n---\n> #{e4.to_s}\n"
|
47
|
+
|
48
|
+
diff = SafeDiff.new e1, e5
|
49
|
+
assert_equal diff.operation, SafeDiff::CHANGE
|
50
|
+
assert_equal diff.to_s, "#{SafeDiff::CHANGE}\n< #{e1.to_s}\n---\n> #{e5.to_s}\n"
|
51
|
+
end
|
52
|
+
end
|
data/test/tc_safeutils.rb
CHANGED
@@ -42,4 +42,60 @@ class SafeUtilsTest < Test::Unit::TestCase
|
|
42
42
|
# Make sure the directory exists
|
43
43
|
FileUtils::cd dir
|
44
44
|
end
|
45
|
+
|
46
|
+
def test_diff
|
47
|
+
f1 = SafeFile.new("password", ".")
|
48
|
+
f2 = SafeFile.new("password", ".", ".safe2.xml")
|
49
|
+
|
50
|
+
f1.insert('apple', 'baker', 'charlie')
|
51
|
+
diffs = SafeUtils.get_diffs(f1, f2)
|
52
|
+
assert_equal 1, diffs.length
|
53
|
+
assert_equal "m\n< apple\tbaker\tcharlie\n", diffs[0].to_s
|
54
|
+
|
55
|
+
f2.insert('apple', 'baker', 'charlie')
|
56
|
+
diffs = SafeUtils.get_diffs(f1, f2)
|
57
|
+
assert_equal 0, diffs.length
|
58
|
+
|
59
|
+
f2.insert('foo', 'bar', 'baz')
|
60
|
+
diffs = SafeUtils.get_diffs(f1, f2)
|
61
|
+
assert_equal 1, diffs.length
|
62
|
+
assert_equal "o\n> foo\tbar\tbaz\n", diffs[0].to_s
|
63
|
+
|
64
|
+
f2.insert('apple', 'ibm', 'compaq')
|
65
|
+
f2.delete('foo')
|
66
|
+
diffs = SafeUtils.get_diffs(f1, f2)
|
67
|
+
assert_equal 1, diffs.length
|
68
|
+
assert_equal "c\n< apple\tbaker\tcharlie\n---\n> apple\tibm\tcompaq\n", diffs[0].to_s
|
69
|
+
|
70
|
+
FileUtils::rm("./.safe2.xml")
|
71
|
+
FileUtils::rm("./.safe.xml")
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_merge
|
75
|
+
f1 = SafeFile.new("password", ".")
|
76
|
+
f2 = SafeFile.new("password", ".", ".safe2.xml")
|
77
|
+
|
78
|
+
f1.insert('apple', 'baker', 'charlie')
|
79
|
+
f1.insert('one', 'baker', 'charlie')
|
80
|
+
f1.insert('two', 'baker', 'charlie')
|
81
|
+
f1.insert('three', 'baker', 'charlie')
|
82
|
+
f1.insert('four', 'baker', 'charlie')
|
83
|
+
f1.insert('five', 'baker', 'charlie')
|
84
|
+
|
85
|
+
f2.insert('three', 'baker', 'charlie')
|
86
|
+
f2.insert('four', 'goober', 'raisinet')
|
87
|
+
f2.insert('five', 'coke', 'pepsi')
|
88
|
+
f2.insert('six', 'baker', 'charlie')
|
89
|
+
f2.insert('seven', 'baker', 'charlie')
|
90
|
+
f2.insert('eight', 'baker', 'charlie')
|
91
|
+
|
92
|
+
diffs = SafeUtils.get_diffs(f1, f2)
|
93
|
+
SafeUtils.do_merge(f1, diffs, true)
|
94
|
+
assert_equal 9, f1.count
|
95
|
+
assert_equal "four\tgoober\traisinet", f1.entries['four'].to_s
|
96
|
+
assert_equal "five\tcoke\tpepsi", f1.entries['five'].to_s
|
97
|
+
|
98
|
+
FileUtils::rm("./.safe2.xml")
|
99
|
+
FileUtils::rm("./.safe.xml")
|
100
|
+
end
|
45
101
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.5"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob Warner
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-04-
|
12
|
+
date: 2008-04-06 00:00:00 -04:00
|
13
13
|
default_executable: safe
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -40,6 +40,7 @@ extra_rdoc_files: []
|
|
40
40
|
|
41
41
|
files:
|
42
42
|
- README
|
43
|
+
- lib/safediff.rb
|
43
44
|
- lib/safeentry.rb
|
44
45
|
- lib/safefile.rb
|
45
46
|
- lib/safeutils.rb
|
@@ -73,6 +74,7 @@ signing_key:
|
|
73
74
|
specification_version: 2
|
74
75
|
summary: A command-line password storage program
|
75
76
|
test_files:
|
77
|
+
- test/tc_safediff.rb
|
76
78
|
- test/tc_safeentry.rb
|
77
79
|
- test/tc_safefile.rb
|
78
80
|
- test/tc_safeutils.rb
|