melon 0.6.1 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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