root / bin / atom-cp

Revision 199, 3.4 kB (checked in by Brendan Taylor <whateley@…>, 5 months ago)

more-tools

Line 
1#!/usr/bin/env ruby
2
3=begin
4Usage: 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
11require 'atom/tools'
12include Atom::Tools
13
14def parse_options
15  options = { }
16
17  opts = OptionParser.new do |opts|
18    opts.banner = <<END
19Usage: #{$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
25END
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
46end
47
48# like dir_to_entries, but returns an Array of [slug, entry] pairs
49def 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
60end
61
62# like entries_to_http, but takes an Array of [slug, entry] pairs
63def 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
69end
70
71# like entries_to_dir, but takes an Array of [slug, entry] pairs
72def 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
90end
91
92def 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
125end
126
127def 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
139end
140
141# make up a slug based on the alternate link
142def infer_slug entry
143  slug = nil
144  alt = e.links.find { |l| l['rel'] == 'alternate' }
145
146  alt and alt['href'].split('/').last
147end
148
149if __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
159end
Note: See TracBrowser for help on using the browser.