melon 0.6.1 → 0.7
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/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
|