melon 0.6.1 → 0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -1
- data/features/list.feature +17 -1
- data/features/remove.feature +35 -0
- data/features/step_definitions/basic_steps.rb +0 -5
- data/features/step_definitions/hash_steps.rb +15 -0
- data/lib/melon/commands.rb +1 -7
- data/lib/melon/commands/list.rb +8 -3
- data/lib/melon/commands/remove.rb +65 -0
- data/lib/melon/version.rb +1 -1
- metadata +9 -17
- data/lib/melon/example.rb +0 -68
data/History.txt
CHANGED
data/features/list.feature
CHANGED
@@ -3,7 +3,7 @@ Feature: List
|
|
3
3
|
As a user
|
4
4
|
I should be able to get a list of tracked files
|
5
5
|
|
6
|
-
|
6
|
+
Background:
|
7
7
|
Given a file named "test_file" with:
|
8
8
|
"""
|
9
9
|
Test file 1
|
@@ -13,6 +13,22 @@ Feature: List
|
|
13
13
|
Test file 2
|
14
14
|
"""
|
15
15
|
And I run "melon -d test.db add -q test_file file_test"
|
16
|
+
|
17
|
+
|
18
|
+
Scenario: Listing files
|
16
19
|
When I run "melon -d test.db list"
|
17
20
|
Then the output should contain "test_file"
|
18
21
|
And the output should contain "file_test"
|
22
|
+
And the output should contain 2 hashes
|
23
|
+
|
24
|
+
Scenario: Listing paths only
|
25
|
+
When I run "melon -d test.db list -p"
|
26
|
+
Then the output should contain "test_file"
|
27
|
+
And the output should contain "file_test"
|
28
|
+
And the output should not contain a hash
|
29
|
+
|
30
|
+
Scenario: Listing hashes only
|
31
|
+
When I run "melon -d test.db list -c"
|
32
|
+
Then the output should not contain "test_file"
|
33
|
+
And the output should not contain "file_test"
|
34
|
+
And the output should contain 2 hashes
|
@@ -0,0 +1,35 @@
|
|
1
|
+
Feature: Remove file from the database
|
2
|
+
In order to get rid of crappy media
|
3
|
+
As a user
|
4
|
+
I should be able to delete from the database
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given a file named "test_file" with:
|
8
|
+
"""
|
9
|
+
I am an unassuming test file
|
10
|
+
"""
|
11
|
+
And a file named "same_file" with:
|
12
|
+
"""
|
13
|
+
I am an unassuming test file
|
14
|
+
"""
|
15
|
+
And a file named "different_file" with:
|
16
|
+
"""
|
17
|
+
I am a unique flower
|
18
|
+
"""
|
19
|
+
And I run "melon -d test.db add -q test_file"
|
20
|
+
|
21
|
+
Scenario: Removing a tracked file
|
22
|
+
When I run "melon -d test.db remove test_file"
|
23
|
+
Then the output should contain "test_file"
|
24
|
+
# TODO: demand empty list
|
25
|
+
|
26
|
+
Scenario: Removing a tracked file by hash
|
27
|
+
When I run "melon -d test.db remove same_file"
|
28
|
+
Then the output should contain "test_file"
|
29
|
+
|
30
|
+
Scenario: Attempting to removean untracked file
|
31
|
+
When I run "melon -d test.db remove different_file"
|
32
|
+
Then the output should contain "untracked file"
|
33
|
+
And the output should contain "different_file"
|
34
|
+
|
35
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'aruba/api'
|
2
|
+
|
3
|
+
Then /^the output should contain (a|\d+) hash(?:es)?$/ do |count|
|
4
|
+
count = 1 if count == 'a'
|
5
|
+
count = count.to_i
|
6
|
+
|
7
|
+
lines = all_output.split("\n")
|
8
|
+
match_count = 0
|
9
|
+
lines.each { |line| match_count += 1 if line.match(/[a-f0-9]{40}/) }
|
10
|
+
match_count.should == count
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^the output should not contain a hash$/ do
|
14
|
+
all_output.split('\n').each { |l| l.should_not match(/[a-f0-9]{40}/) }
|
15
|
+
end
|
data/lib/melon/commands.rb
CHANGED
@@ -20,16 +20,10 @@ module Melon
|
|
20
20
|
end
|
21
21
|
|
22
22
|
|
23
|
-
# 1.0 list
|
24
|
-
# TODO: needs a 'remove' command, or some way to deal with deletes/renames
|
25
|
-
# remove: given a tracked file, removes it
|
26
|
-
# given an untracked file, it hashes it
|
27
|
-
# and attempts to remove it by hash
|
28
|
-
# TODO: list needs --paths(only) and --hashes(only)
|
29
|
-
#
|
30
23
|
# post-1.0
|
31
24
|
# TODO: needs a 'verify' command to check integrity of database
|
32
25
|
# both internal 2-hash consistency (consistency) and db<->filesystem
|
33
26
|
# matching up (integrity) [file exists, hashes match]
|
27
|
+
#
|
34
28
|
end
|
35
29
|
end
|
data/lib/melon/commands/list.rb
CHANGED
@@ -8,11 +8,13 @@ module Melon
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def parser_options(parser)
|
11
|
-
parser.on("-p", "--paths", "
|
11
|
+
parser.on("-p", "--paths", "Print only paths") do
|
12
12
|
options.only_paths = true
|
13
13
|
end
|
14
14
|
# TODO: re-enable this as -h after help command goes in
|
15
|
-
|
15
|
+
parser.on("-c", "--checksums", "print only hashes") do
|
16
|
+
options.only_hashes = true
|
17
|
+
end
|
16
18
|
end
|
17
19
|
|
18
20
|
def verify_args
|
@@ -24,7 +26,10 @@ module Melon
|
|
24
26
|
|
25
27
|
options.database.transaction do
|
26
28
|
options.database[:by_hash].each_pair do |hash, path|
|
27
|
-
|
29
|
+
out = [path, hash]
|
30
|
+
out.delete(path) if options.only_hashes
|
31
|
+
out.delete(hash) if options.only_paths
|
32
|
+
puts out.join(":")
|
28
33
|
end
|
29
34
|
end
|
30
35
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'melon/commands/base'
|
2
|
+
require 'melon/commands/common_options'
|
3
|
+
|
4
|
+
module Melon
|
5
|
+
module Commands
|
6
|
+
class Remove < Base
|
7
|
+
def self.description
|
8
|
+
"Remove a file from the database"
|
9
|
+
end
|
10
|
+
|
11
|
+
def helptext
|
12
|
+
<<EOS
|
13
|
+
For each argument, the database is checked for the path of that
|
14
|
+
argument. If present, it is removed. If not, the database is
|
15
|
+
checked for the hash of the argument. Once again, the record
|
16
|
+
in the database is removed if found.
|
17
|
+
|
18
|
+
If a file is found, the path that was in the database is printed.
|
19
|
+
EOS
|
20
|
+
end
|
21
|
+
|
22
|
+
def usageargs
|
23
|
+
"FILE [FILE [FILE ...]]"
|
24
|
+
end
|
25
|
+
|
26
|
+
def parser_options(parser)
|
27
|
+
CommonOptions.recursive(parser, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
parse_options!
|
32
|
+
|
33
|
+
if options.recursive
|
34
|
+
self.args = recursively_expand(args)
|
35
|
+
end
|
36
|
+
|
37
|
+
options.database.transaction do
|
38
|
+
args.each do |arg|
|
39
|
+
filename = File.expand_path(arg)
|
40
|
+
filename = resolve_symlinks(filename)
|
41
|
+
|
42
|
+
if File.directory?(filename)
|
43
|
+
error "argument is a directory: #{arg}"
|
44
|
+
end
|
45
|
+
|
46
|
+
if options.database[:by_path][filename]
|
47
|
+
hash = options.database[:by_path].delete(filename)
|
48
|
+
options.database[:by_hash].delete(hash)
|
49
|
+
puts filename
|
50
|
+
else
|
51
|
+
hash = Hasher.digest(filename)
|
52
|
+
if options.database[:by_hash][hash]
|
53
|
+
filename = options.database[:by_hash].delete(hash)
|
54
|
+
options.database[:by_path].delete(filename)
|
55
|
+
puts filename
|
56
|
+
else
|
57
|
+
error("untracked file: #{arg}")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/melon/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: melon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 5
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 0.6.1
|
7
|
+
- 7
|
8
|
+
version: "0.7"
|
11
9
|
platform: ruby
|
12
10
|
authors:
|
13
11
|
- Andrew Roberts
|
@@ -15,18 +13,16 @@ autorequire:
|
|
15
13
|
bindir: bin
|
16
14
|
cert_chain: []
|
17
15
|
|
18
|
-
date:
|
16
|
+
date: 2012-09-12 00:00:00 -04:00
|
19
17
|
default_executable: melon
|
20
18
|
dependencies:
|
21
19
|
- !ruby/object:Gem::Dependency
|
22
20
|
name: digestif
|
23
21
|
prerelease: false
|
24
22
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 31
|
30
26
|
segments:
|
31
27
|
- 1
|
32
28
|
- 0
|
@@ -38,11 +34,9 @@ dependencies:
|
|
38
34
|
name: cucumber
|
39
35
|
prerelease: false
|
40
36
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
|
-
hash: 3
|
46
40
|
segments:
|
47
41
|
- 0
|
48
42
|
version: "0"
|
@@ -52,11 +46,9 @@ dependencies:
|
|
52
46
|
name: aruba
|
53
47
|
prerelease: false
|
54
48
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
49
|
requirements:
|
57
50
|
- - ">="
|
58
51
|
- !ruby/object:Gem::Version
|
59
|
-
hash: 3
|
60
52
|
segments:
|
61
53
|
- 0
|
62
54
|
version: "0"
|
@@ -83,8 +75,10 @@ files:
|
|
83
75
|
- features/edges.feature
|
84
76
|
- features/help.feature
|
85
77
|
- features/list.feature
|
78
|
+
- features/remove.feature
|
86
79
|
- features/show.feature
|
87
80
|
- features/step_definitions/basic_steps.rb
|
81
|
+
- features/step_definitions/hash_steps.rb
|
88
82
|
- features/support/env.rb
|
89
83
|
- lib/melon.rb
|
90
84
|
- lib/melon/cli.rb
|
@@ -95,8 +89,8 @@ files:
|
|
95
89
|
- lib/melon/commands/common_options.rb
|
96
90
|
- lib/melon/commands/help.rb
|
97
91
|
- lib/melon/commands/list.rb
|
92
|
+
- lib/melon/commands/remove.rb
|
98
93
|
- lib/melon/commands/show.rb
|
99
|
-
- lib/melon/example.rb
|
100
94
|
- lib/melon/hasher.rb
|
101
95
|
- lib/melon/helpers.rb
|
102
96
|
- lib/melon/version.rb
|
@@ -117,27 +111,23 @@ rdoc_options: []
|
|
117
111
|
require_paths:
|
118
112
|
- lib
|
119
113
|
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
-
none: false
|
121
114
|
requirements:
|
122
115
|
- - ">="
|
123
116
|
- !ruby/object:Gem::Version
|
124
|
-
hash: 3
|
125
117
|
segments:
|
126
118
|
- 0
|
127
119
|
version: "0"
|
128
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
121
|
requirements:
|
131
122
|
- - ">="
|
132
123
|
- !ruby/object:Gem::Version
|
133
|
-
hash: 3
|
134
124
|
segments:
|
135
125
|
- 0
|
136
126
|
version: "0"
|
137
127
|
requirements: []
|
138
128
|
|
139
129
|
rubyforge_project:
|
140
|
-
rubygems_version: 1.3.
|
130
|
+
rubygems_version: 1.3.6
|
141
131
|
signing_key:
|
142
132
|
specification_version: 3
|
143
133
|
summary: A media catalog
|
@@ -147,8 +137,10 @@ test_files:
|
|
147
137
|
- features/edges.feature
|
148
138
|
- features/help.feature
|
149
139
|
- features/list.feature
|
140
|
+
- features/remove.feature
|
150
141
|
- features/show.feature
|
151
142
|
- features/step_definitions/basic_steps.rb
|
143
|
+
- features/step_definitions/hash_steps.rb
|
152
144
|
- features/support/env.rb
|
153
145
|
- spec/melon/cli_spec.rb
|
154
146
|
- spec/melon/database_spec.rb
|
data/lib/melon/example.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'subcommand'
|
3
|
-
|
4
|
-
require 'melon/version'
|
5
|
-
|
6
|
-
module Melon
|
7
|
-
class CLI
|
8
|
-
def self.execute(arguments=[])
|
9
|
-
new(arguments).run
|
10
|
-
end
|
11
|
-
|
12
|
-
attr_accessor :arguments
|
13
|
-
|
14
|
-
def initialize(arguments)
|
15
|
-
self.arguments = arguments
|
16
|
-
end
|
17
|
-
|
18
|
-
def run
|
19
|
-
# command may be nil, if no command is given
|
20
|
-
command = parser.parse!(arguments)
|
21
|
-
end
|
22
|
-
|
23
|
-
def parser
|
24
|
-
@parser ||= OptionParser.new do |opts|
|
25
|
-
opts.banner = "Example of what option parsing should look like"
|
26
|
-
|
27
|
-
opts.on("-d", "--database=PATH", String,
|
28
|
-
"Path to Melon's sqlite database.",
|
29
|
-
" (default ~/.melon/melon.db)") do |arg|
|
30
|
-
self.options[:database] = arg
|
31
|
-
end
|
32
|
-
|
33
|
-
opts.on("-v", "--version",
|
34
|
-
"Display the program version.") { puts "0.0.0" }
|
35
|
-
opts.on("-h", "--help",
|
36
|
-
"Show this help message.") { puts parser }
|
37
|
-
opts.separator ""
|
38
|
-
|
39
|
-
opts.command :create, "description text" do |subopts|
|
40
|
-
subopts.banner "create: create a directory, somewhere"
|
41
|
-
|
42
|
-
subopts.on("-f" "--force",
|
43
|
-
"Force creation.") { self.options[:force] = true }
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
opts.separator "To see a list of commands, use 'melon help commands'."
|
48
|
-
opts.separator "To get help with a specific command," +
|
49
|
-
" use 'melon help COMMAND'."
|
50
|
-
end
|
51
|
-
|
52
|
-
# OptionParser#command adds lazy option parsers to an array
|
53
|
-
# of subcommands
|
54
|
-
#
|
55
|
-
# melon help COMMAND prints the appropriate option
|
56
|
-
#
|
57
|
-
# PARSING:
|
58
|
-
# the option parser knows what the commands are at parse time
|
59
|
-
# so, scan the parse!() argument for the first command and pivot on
|
60
|
-
# it
|
61
|
-
#
|
62
|
-
# pre-cmd goes to the main option_parser.parse
|
63
|
-
# cmd goes into a string, is returned
|
64
|
-
# post-cmd goes to cmd parser.parse!()
|
65
|
-
#
|
66
|
-
# possibly implement that behavior for order! as well
|
67
|
-
end
|
68
|
-
end
|