atom-tools 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING CHANGED
@@ -6,13 +6,13 @@ deal in the Software without restriction, including without limitation the
6
6
  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
7
  sell copies of the Software, and to permit persons to whom the Software is
8
8
  furnished to do so, subject to the following conditions:
9
-
9
+
10
10
  The above copyright notice and this permission notice shall be included in
11
11
  all copies or substantial portions of the Software.
12
-
12
+
13
13
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
14
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
15
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
- THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
17
  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
18
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README CHANGED
@@ -43,10 +43,10 @@ Things are explained in more detail in the RDoc.
43
43
  coll = service.workspaces.first.collections.first
44
44
  # => <http://necronomicorp.com/testatom?app entries: 0 title='testing: entry endpoint'>
45
45
 
46
- coll.update!
46
+ coll.feed.update!
47
47
  # => <http://necronomicorp.com/testatom?app entries: 10 title='testing the APP'>
48
48
 
49
- entry = coll.entries.first
49
+ entry = coll.feed.entries.first
50
50
  entry.title
51
51
  # => 'html entities'#text
52
52
 
@@ -57,47 +57,7 @@ Things are explained in more detail in the RDoc.
57
57
  coll.put! entry
58
58
  # => #<Net::HTTPOK 200 OK readbody=true>
59
59
 
60
- coll.entries.first.title
60
+ coll.feed.entries.first.title
61
61
  # => 'HTML entities'#text
62
62
 
63
- For details on authentication, see the documentation for Atom::HTTP
64
-
65
- == Advanced Use
66
-
67
- === Extension Elements
68
-
69
- irt = REXML::Element.new("in-reply-to")
70
- irt.add_namespace "http://purl.org/syndication/thread/1.0"
71
-
72
- irt.attributes["ref"] = "tag:entries.com,2005:1"
73
-
74
- entry.extensions << irt
75
-
76
- entry.to_s
77
- # => '<entry xmlns="http://www.w3.org/2005/Atom"><in-reply-to ref="tag:entries.com,2005:1" xmlns="http://purl.org/syndication/thread/1.0"/></entry>'
78
-
79
- == YAML
80
-
81
- if you feel like writing this stuff by hand, atom-tools can slurp an
82
- atom:entry from YAML:
83
-
84
- require "atom/yaml"
85
-
86
- yaml = <<END
87
- title: Atom-Drunk Pirates Run Amok!
88
- tags: tag1 tag2
89
- authors:
90
- -
91
- name: Brendan Taylor
92
- email: whateley@gmail.com
93
- -
94
- name: Harvey
95
- uri: http://fake.com/
96
-
97
- content: |
98
- <p>blah blah blah blah</p>
99
-
100
- <p>and so on.</p>
101
- END
102
-
103
- entry = Atom::Entry.from_yaml(yaml)
63
+ For details on authentication, see the documentation for Atom::HTTP.
data/Rakefile CHANGED
@@ -2,11 +2,12 @@ require "rake"
2
2
  require "rake/testtask"
3
3
  require "rake/rdoctask"
4
4
  require "rake/gempackagetask"
5
+ require "spec/rake/spectask"
5
6
 
6
7
  require "rake/clean"
7
8
 
8
9
  NAME = "atom-tools"
9
- VERS = "1.0.0"
10
+ VERS = "2.0.0"
10
11
 
11
12
  # the following from markaby-0.5's tools/rakehelp
12
13
  def setup_tests
@@ -67,7 +68,13 @@ def setup_gem(pkg_name, pkg_version, author, summary, dependencies, test_file)
67
68
  end
68
69
  end
69
70
 
70
- task :default => [:package]
71
+ task :default => [:spec]
72
+ desc 'Run all specs and generate report for spec results and code coverage'
73
+ Spec::Rake::SpecTask.new('spec') do |t|
74
+ t.spec_opts = ["--format", "html:report.html", '--diff']
75
+ t.fail_on_error = false
76
+ t.rcov = true
77
+ end
71
78
 
72
79
  setup_tests
73
80
  setup_rdoc ['README', 'lib/**/*.rb']
data/bin/atom-cp ADDED
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ =begin
4
+ Usage: atom-cp [options] source destination
5
+ copy the contents of an Atom Collection
6
+
7
+ 'source' and 'destination' can be a path on the local filesystem, the
8
+ URL of an Atom Collection or '-' for stdin/stdout
9
+ =end
10
+
11
+ require 'atom/tools'
12
+ include Atom::Tools
13
+
14
+ def parse_options
15
+ options = { }
16
+
17
+ opts = OptionParser.new do |opts|
18
+ opts.banner = <<END
19
+ Usage: #{$0} [options] source destination
20
+ copy an Atom Collection
21
+
22
+ 'source' and 'destination' can be a path on the local filesystem, the
23
+ URL of an Atom Collection or '-' for stdin/stdout
24
+
25
+ END
26
+
27
+ opts.on('-c', '--complete', "follow previous and next links in the source feed to obtain the entire logical feed") do
28
+ options[:complete] = true
29
+ end
30
+
31
+ opts.on('-s', '--infer-slugs', 'try to infer entry slugs') { options[:infer_slugs] = true }
32
+
33
+ opts.on('-v', '--verbose') { options[:verbose] = true }
34
+
35
+ atom_options opts, options
36
+ end
37
+
38
+ opts.parse!(ARGV)
39
+
40
+ if ARGV.length != 2
41
+ puts opts
42
+ exit
43
+ end
44
+
45
+ options
46
+ end
47
+
48
+ # like dir_to_entries, but returns an Array of [slug, entry] pairs
49
+ def dir_to_entries_with_slug path
50
+ raise ArgumentError, "#{path} is not a directory" unless File.directory? path
51
+
52
+ Dir[path+'/*.atom'].map do |e|
53
+ slug = e.match(/.*\/(.*)\.atom/)[1]
54
+ slug = nil if slug and slug.match /^0x/
55
+
56
+ entry = Atom::Entry.parse(File.read(e))
57
+
58
+ [slug, entry]
59
+ end
60
+ end
61
+
62
+ # like entries_to_http, but takes an Array of [slug, entry] pairs
63
+ def entries_to_http_with_slug entries, url, http = Atom::HTTP.new
64
+ coll = Atom::Collection.new url, http
65
+
66
+ entries.each do |slug, entry|
67
+ coll.post! entry, slug
68
+ end
69
+ end
70
+
71
+ # like entries_to_dir, but takes an Array of [slug, entry] pairs
72
+ def entries_to_dir_with_slug entries, path
73
+ if File.exists? path
74
+ raise "directory #{path} already exists"
75
+ else
76
+ Dir.mkdir path
77
+ end
78
+
79
+ entries.each do |slug,entry|
80
+ e = entry.to_s
81
+
82
+ new_filename = if slug
83
+ path + '/' + slug + '.atom'
84
+ else
85
+ path + '/0x' + MD5.new(e).hexdigest[0,8] + '.atom'
86
+ end
87
+
88
+ File.open(new_filename, 'w') { |f| f.write e }
89
+ end
90
+ end
91
+
92
+ def parse_input_with_slug source, options
93
+ entries = if source.match /^http/
94
+ http = Atom::HTTP.new
95
+
96
+ setup_http http, options
97
+
98
+ http_to_entries(source, options[:complete], http).map do |e|
99
+ [nil, e]
100
+ end
101
+ elsif source == '-'
102
+ stdin_to_entries.map do |e|
103
+ [nil, e]
104
+ end
105
+ else
106
+ dir_to_entries_with_slug source
107
+ end
108
+
109
+ if options[:verbose]
110
+ entries.each do |slug,entry|
111
+ print "got #{entry.title} "
112
+ puts (slug ? "(/#{slug})" : '')
113
+ end
114
+ end
115
+
116
+ if options[:infer_slugs]
117
+ entries.map! do |slug,entry|
118
+ slug ||= infer_slug entry
119
+
120
+ [slug, entry]
121
+ end
122
+ end
123
+
124
+ entries
125
+ end
126
+
127
+ def write_output_with_slug entries, dest, options
128
+ if dest.match /^http/
129
+ http = Atom::HTTP.new
130
+
131
+ setup_http http, options
132
+
133
+ entries_to_http_with_slug entries, dest, http
134
+ elsif dest == '-'
135
+ entries_to_stdout entries.map { |s,e| e }
136
+ else
137
+ entries_to_dir_with_slug entries, dest
138
+ end
139
+ end
140
+
141
+ # make up a slug based on the alternate link
142
+ def infer_slug entry
143
+ slug = nil
144
+ alt = e.links.find { |l| l['rel'] == 'alternate' }
145
+
146
+ alt and alt['href'].split('/').last
147
+ end
148
+
149
+ if __FILE__ == $0
150
+ require 'optparse'
151
+
152
+ options = parse_options
153
+
154
+ source = ARGV[0]
155
+ dest = ARGV[1]
156
+
157
+ entries = parse_input_with_slug source, options
158
+ write_output_with_slug entries, dest, options
159
+ end
data/bin/atom-grep ADDED
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ =begin
4
+ Usage: atom-grep [options] regexp [source]
5
+ prints a feed containing every entry in the source feed whose
6
+ text content matches regexp to stdout
7
+
8
+ 'source' can be a path on the local filesystem, the
9
+ URL of an Atom Collection or '-' for stdin.
10
+ =end
11
+
12
+ require 'atom/tools'
13
+ include Atom::Tools
14
+
15
+ def parse_options
16
+ options = { :regexp_options => 0 }
17
+
18
+ opts = OptionParser.new do |opts|
19
+ opts.banner = <<END
20
+ Usage: #{$0} [options] regexp [source]
21
+ prints a feed containing every entry in the source feed whose
22
+ text content matches regexp to stdout
23
+
24
+ 'source' can be a path on the local filesystem, the
25
+ URL of an Atom Collection or '-' for stdin.
26
+ END
27
+
28
+ opts.on('-c', '--complete', "follow previous and next links in the source feed to obtain the entire logical feed") do
29
+ options[:complete] = true
30
+ end
31
+
32
+ opts.on('-v', '--invert-match', 'select only non-matching entries') do
33
+ options[:invert] = true
34
+ end
35
+
36
+ opts.on('-i', '--ignore-case', 'ignore case distinctions when matching') do
37
+ options[:regexp_options] |= Regexp::IGNORECASE
38
+ end
39
+
40
+ atom_options opts, options
41
+ end
42
+
43
+ opts.parse!(ARGV)
44
+
45
+ if ARGV.length < 1 or ARGV.length > 2
46
+ puts opts
47
+ exit
48
+ end
49
+
50
+ options
51
+ end
52
+
53
+ if __FILE__ == $0
54
+ require 'optparse'
55
+
56
+ options = parse_options
57
+
58
+ regexp = Regexp.new(ARGV[0], options[:regexp_options])
59
+
60
+ source = ARGV[1]
61
+ source ||= '-'
62
+
63
+ entries = parse_input source, options
64
+
65
+ pred = if options[:invert]
66
+ lambda do |e|
67
+ (e.title =~ regexp) or (e.content.to_s =~ regexp)
68
+ end
69
+ else
70
+ lambda do |e|
71
+ (e.title !~ regexp) and (e.content.to_s !~ regexp)
72
+ end
73
+ end
74
+
75
+ entries.reject! &pred
76
+
77
+ entries_to_stdout entries
78
+ end
data/bin/atom-post ADDED
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ =begin
4
+ Usage: atom-post [options] destination [file]
5
+ posts an Atom Entry or a file to an Atom Collection
6
+
7
+ 'destination' is the URL of an Atom Collection
8
+ 'file' is the path to a file to POST (default is stdin)
9
+ =end
10
+
11
+ require 'atom/tools'
12
+ include Atom::Tools
13
+
14
+ def parse_options
15
+ options = {
16
+ :mimetype => 'application/atom+xml;type=entry'
17
+ }
18
+
19
+ opts = OptionParser.new do |opts|
20
+ opts.banner = <<END
21
+ Usage: #{$0} [options] destination [file]
22
+ posts an Atom Entry or a file to an Atom Collection
23
+
24
+ 'destination' is the URL of an Atom Collection
25
+ 'file' is the path to a file to POST (default is stdin)
26
+ END
27
+
28
+ opts.on('-m', '--mime-type TYPE', 'what to send in the Content-Type header') do |t|
29
+ options[:mimetype] = t
30
+ end
31
+
32
+ opts.on('-s', '--slug SLUG') do |s|
33
+ options[:slug] = s
34
+ end
35
+
36
+ atom_options opts, options
37
+ end
38
+
39
+ opts.parse!(ARGV)
40
+
41
+ if ARGV.length < 1 or ARGV.length > 2
42
+ puts opts
43
+ exit
44
+ end
45
+
46
+ options
47
+ end
48
+
49
+ if __FILE__ == $0
50
+ require 'optparse'
51
+
52
+ options = parse_options
53
+
54
+ dest = ARGV[0]
55
+
56
+ data = if ARGV[1]
57
+ File.read(ARGV[1])
58
+ else
59
+ $stdin.read
60
+ end
61
+
62
+ http = Atom::HTTP.new
63
+ setup_http http, options
64
+
65
+ headers = { 'Content-Type' => options[:mimetype] }
66
+
67
+ if options[:slug]
68
+ headers['Slug'] = options[:slug]
69
+ end
70
+
71
+ http.post dest, data, headers
72
+ end
data/bin/atom-purge ADDED
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ =begin
4
+ Usage: atom-purge [options] collection
5
+ delete all the entries in an Atom Collection
6
+
7
+ 'collection' can be a path on the local filesystem, the
8
+ URL of an Atom Collection or '-' for stdin. the feed is parsed
9
+ and every Member URI found in it is DELETEd.
10
+ =end
11
+
12
+ require 'atom/tools'
13
+ include Atom::Tools
14
+
15
+ def parse_options
16
+ options = {}
17
+
18
+ opts = OptionParser.new do |opts|
19
+ opts.banner = <<END
20
+ Usage: #{$0} [options] collection
21
+ delete all the entries in an Atom Collection
22
+
23
+ 'collection' can be a path on the local filesystem, the
24
+ URL of an Atom Collection or '-' for stdin. the feed is parsed
25
+ and every Member URI found in it is DELETEd.
26
+
27
+ END
28
+
29
+ opts.on('-c', '--no-complete', "don't follow previous and next links in the source feed") do
30
+ options[:complete] = false
31
+ end
32
+
33
+ opts.on('-v', '--verbose') { options[:verbose] = true }
34
+
35
+ opts.on('-i', '--interactive', "ask before each DELETE") { options[:interactive] = true }
36
+
37
+ atom_options opts, options
38
+ end
39
+
40
+ opts.parse!(ARGV)
41
+
42
+ if ARGV.length != 1
43
+ puts opts
44
+ exit
45
+ end
46
+
47
+ options
48
+ end
49
+
50
+ if __FILE__ == $0
51
+ require 'optparse'
52
+
53
+ options = parse_options
54
+
55
+ source = ARGV[0]
56
+ dest = ARGV[1]
57
+
58
+ entries = parse_input source, options
59
+
60
+ http = Atom::HTTP.new
61
+ setup_http http, options
62
+
63
+ tty = File.open('/dev/tty', 'w+') if options[:interactive]
64
+
65
+ uris = entries.each do |e|
66
+ next unless (uri = e.edit_url)
67
+
68
+ puts "deleting #{uri}" if options[:verbose]
69
+
70
+ if options[:interactive]
71
+ tty.puts "delete #{uri}"
72
+ tty.puts "title: #{e.title}"
73
+ tty.puts e.content.to_s
74
+ tty.puts
75
+ tty.print "? "
76
+
77
+ next unless ['y', 'yes'].member? tty.gets.chomp
78
+ end
79
+
80
+ http.delete uri
81
+ end
82
+ end