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.
@@ -1,4 +1,8 @@
1
- === 0.6.0 2011-02-10
1
+ === 0.7.0 2012-09-12
2
+ * Major improvements
3
+ * Added 'remove' command
4
+
5
+ === 0.6.1 2011-02-10
2
6
  * Minor improvements
3
7
  * Fixed symlink-related bug
4
8
 
@@ -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
- Scenario: Listing files
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
+
@@ -8,8 +8,3 @@ Then /^the output should start with "([^"]*)"$/ do |arg1|
8
8
  all_output.should match(/^#{arg1}/)
9
9
  end
10
10
 
11
- Then /^the output should contain a hash$/ do
12
- all_output.should match(/[a-fA-F0-9]{20}/)
13
- end
14
-
15
-
@@ -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
@@ -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
@@ -8,11 +8,13 @@ module Melon
8
8
  end
9
9
 
10
10
  def parser_options(parser)
11
- parser.on("-p", "--paths", "print only paths") do
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
- # parser.on("--hashes", "print only hashes") { options.only_hashes = true }
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
- puts "#{path}:#{hash}"
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
@@ -1,6 +1,6 @@
1
1
  module Melon
2
2
  def self.version
3
- "0.6.1"
3
+ "0.7"
4
4
  end
5
5
 
6
6
  def self.version_string
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
- - 6
9
- - 1
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: 2011-02-10 00:00:00 -05:00
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.7
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
@@ -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