Revision | 862cc891e71dbfbc3cd392df12d5653ead705717 (tree) |
---|---|
Time | 2016-05-10 17:54:31 |
Author | Tatsuki Sugiura <sugi@nemu...> |
Commiter | Tatsuki Sugiura |
Pertial upload support by target_dir argument.
@@ -5,8 +5,8 @@ module OSDN; module CLI; module Command | ||
5 | 5 | puts "Options:" |
6 | 6 | puts " -n --dry-run Do noting (use with global -v to inspect)" |
7 | 7 | puts " -p --project=<project> Target project (numeric id or name)" |
8 | - #puts " --package=<project> Target package (numeric id)" | |
9 | - #puts " --release=<project> Target release (numeric id)" | |
8 | + puts " --package=<package-id> Target package (numeric id)" | |
9 | + puts " --release=<release-id> Target release (numeric id)" | |
10 | 10 | puts " -v --visibility=<public|private|hidden>" |
11 | 11 | puts " Default visibility for newly created items" |
12 | 12 | puts " --force-digest Calc local file digest forcely" |
@@ -17,7 +17,8 @@ module OSDN; module CLI; module Command | ||
17 | 17 | opts = GetoptLong.new( |
18 | 18 | [ '--dry-run', '-n', GetoptLong::NO_ARGUMENT ], |
19 | 19 | [ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ], |
20 | - [ '--release', '-r', GetoptLong::REQUIRED_ARGUMENT ], | |
20 | + [ '--package', GetoptLong::REQUIRED_ARGUMENT ], | |
21 | + [ '--release', GetoptLong::REQUIRED_ARGUMENT ], | |
21 | 22 | [ '--visibility', '-v', GetoptLong::REQUIRED_ARGUMENT ], |
22 | 23 | [ '--force-digest', GetoptLong::NO_ARGUMENT], |
23 | 24 | ) |
@@ -26,12 +27,12 @@ module OSDN; module CLI; module Command | ||
26 | 27 | when '--project' |
27 | 28 | arg.empty? or |
28 | 29 | @target_proj = arg |
29 | - #when '--release' | |
30 | - # arg.empty? or | |
31 | - # @target_release = arg | |
32 | - #when '--package' | |
33 | - # arg.empty? or | |
34 | - # @target_package = arg | |
30 | + when '--release' | |
31 | + arg.empty? or | |
32 | + @target_release = arg | |
33 | + when '--package' | |
34 | + arg.empty? or | |
35 | + @target_package = arg | |
35 | 36 | when '--visibility' |
36 | 37 | unless %w(public private hidden).member?(arg) |
37 | 38 | logger.fatal "Invalid visibility status: #{arg}" |
@@ -48,127 +49,147 @@ module OSDN; module CLI; module Command | ||
48 | 49 | @target_dir = Pathname.new(ARGV.shift || '.') |
49 | 50 | proj_info = api.get_project target_proj # check project existance |
50 | 51 | |
51 | - Pathname.glob(@target_dir+'*').sort.each do |pdir| | |
52 | - if cur_pkgid = load_variables(pdir).package_id | |
53 | - # check package existance on server | |
52 | + vars = load_variables(@target_dir) | |
53 | + | |
54 | + if @target_release || vars.release_id | |
55 | + process_release(@target_dir) | |
56 | + elsif @target_package || vars.package_id | |
57 | + process_package(@target_dir) | |
58 | + else | |
59 | + Pathname.glob(@target_dir+'*').sort.each do |pdir| | |
60 | + process_package(pdir) | |
61 | + end | |
62 | + end | |
63 | + end | |
64 | + | |
65 | + def self.description | |
66 | + "Upload local file tree and create package/release implicitly." | |
67 | + end | |
68 | + | |
69 | + def process_package(pdir) | |
70 | + if cur_pkgid = load_variables(pdir).package_id | |
71 | + # check package existance on server | |
72 | + begin | |
73 | + api.get_package target_proj, target_package(pdir) | |
74 | + rescue OSDNClient::ApiError => e | |
54 | 75 | begin |
55 | - api.get_package target_proj, target_package(pdir) | |
56 | - rescue OSDNClient::ApiError => e | |
57 | - begin | |
58 | - err = JSON.parse(e.response_body) | |
59 | - rescue | |
60 | - raise e | |
61 | - end | |
62 | - if err['status'] == 404 | |
63 | - logger.warn "Package ##{cur_pkgid} has been deleted on server and local directory '#{pdir}' remains. You can delete the local directory or delete '#{pdir}/.osdn.vars' file to create a package again with new ID." | |
64 | - next | |
65 | - end | |
76 | + err = JSON.parse(e.response_body) | |
77 | + rescue | |
66 | 78 | raise e |
67 | 79 | end |
68 | - else | |
69 | - logger.info "Createing new package '#{pdir.basename}'" | |
70 | - if @dry_run | |
71 | - pinfo = Hashie::Mash.new id: '(dry-run)', name: pdir.basename, url: '(dry-run)' | |
72 | - else | |
73 | - pinfo = api.create_package target_proj, pdir.basename, visibility: @visibility | |
74 | - update_variables pdir, package_id: pinfo.id | |
80 | + if err['status'] == 404 | |
81 | + logger.warn "Package ##{cur_pkgid} has been deleted on server and local directory '#{pdir}' remains. You can delete the local directory or delete '#{pdir}/.osdn.vars' file to create a package again with new ID." | |
82 | + return false | |
75 | 83 | end |
76 | - $stdout.puts "New package '#{pinfo.name}' has been created; #{pinfo.url}" | |
84 | + raise e | |
77 | 85 | end |
86 | + else | |
87 | + logger.info "Createing new package '#{pdir.basename}'" | |
88 | + if @dry_run | |
89 | + pinfo = Hashie::Mash.new id: '(dry-run)', name: pdir.basename, url: '(dry-run)' | |
90 | + else | |
91 | + pinfo = api.create_package target_proj, pdir.basename, visibility: @visibility | |
92 | + update_variables pdir, package_id: pinfo.id | |
93 | + end | |
94 | + $stdout.puts "New package '#{pinfo.name}' has been created; #{pinfo.url}" | |
95 | + end | |
78 | 96 | |
79 | - Pathname.glob(pdir + '*').sort.each do |rdir| | |
80 | - if !rdir.directory? | |
81 | - logger.warn "Skip normal file '#{rdir}' in release level" | |
82 | - next | |
83 | - end | |
97 | + Pathname.glob(pdir + '*').sort.each do |rdir| | |
98 | + process_release(rdir) | |
99 | + end | |
100 | + end | |
101 | + | |
102 | + def process_release(rdir) | |
103 | + if !rdir.directory? | |
104 | + logger.warn "Skip normal file '#{rdir}' in release level" | |
105 | + return false | |
106 | + end | |
84 | 107 | |
85 | - vars = load_variables(rdir) | |
86 | - rinfo = nil | |
87 | - if vars.release_id | |
88 | - begin | |
89 | - rinfo = api.get_release target_proj, target_package(rdir), target_release(rdir) | |
90 | - rescue OSDNClient::ApiError => e | |
91 | - begin | |
92 | - err = JSON.parse(e.response_body) | |
93 | - rescue | |
94 | - raise e | |
95 | - end | |
96 | - if err['status'] == 404 | |
97 | - logger.warn "Release ##{vars.release_id} has been deleted on server and local directory '#{rdir}' remains. You can delete the local directory or delete '#{rdir}/.osdn.vars' file to create a release again with new ID." | |
98 | - next | |
99 | - end | |
100 | - raise e | |
101 | - end | |
102 | - else vars.release_id | |
103 | - logger.info "Createing new release '#{rdir.basename}'" | |
104 | - if @dry_run | |
105 | - rinfo = Hashie::Mash.new id: '(dry-run)', name: rdir.basename, url: '(dry-run)', files: [] | |
106 | - else | |
107 | - rinfo = api.create_release target_proj, target_package(rdir), rdir.basename, visibility: @visibility | |
108 | - update_variables rdir, release_id: rinfo.id | |
109 | - end | |
110 | - $stdout.puts "New release '#{rinfo.name}' has been created; #{rinfo.url}" | |
108 | + vars = load_variables(rdir) | |
109 | + rinfo = nil | |
110 | + if vars.release_id | |
111 | + begin | |
112 | + rinfo = api.get_release target_proj, target_package(rdir), target_release(rdir) | |
113 | + rescue OSDNClient::ApiError => e | |
114 | + begin | |
115 | + err = JSON.parse(e.response_body) | |
116 | + rescue | |
117 | + raise e | |
111 | 118 | end |
112 | - | |
113 | - Pathname.glob(rdir + '*').sort.each do |file| | |
114 | - if file.directory? | |
115 | - logger.error "Skip direcotry #{file}" | |
116 | - next | |
117 | - end | |
118 | - | |
119 | - vars = load_variables(rdir) | |
120 | - digests = nil | |
121 | - if !@force_digest && vars.local_file_info && | |
122 | - vars.local_file_info[file.basename.to_s] | |
123 | - finfo = vars.local_file_info[file.basename.to_s] | |
124 | - if finfo[:size] == file.size && finfo.mtime == file.mtime | |
125 | - digests = vars.local_file_info[file.basename.to_s].digests | |
126 | - end | |
127 | - end | |
128 | - | |
129 | - unless digests | |
130 | - logger.info "Calculating digest for #{file}..." | |
131 | - digests = { | |
132 | - sha256: hexdigest(Digest::SHA256, file), | |
133 | - sha1: hexdigest(Digest::SHA1, file), | |
134 | - md5: hexdigest(Digest::MD5, file), | |
135 | - } | |
136 | - update_variables rdir, {local_file_info: {file.basename.to_s => {digests: digests, mtime: file.mtime, size: file.size}}} | |
137 | - end | |
138 | - if remote_f = rinfo.files.find { |f| f.name == file.basename.to_s } | |
139 | - if digests.find { |type, dig| dig != remote_f.send("digest_#{type}") } | |
140 | - logger.error "#{file} was changed from remote file! Please delete remote file before uploading new one." | |
141 | - end | |
142 | - logger.info "Skip already uploaded file '#{file}'" | |
143 | - else | |
144 | - logger.info "Uploading file #{file} (#{file.size} bytes)" | |
145 | - if @dry_run | |
146 | - finfo = Hashie::Mash.new id: '(dry-run)', url: '(dry-run)' | |
147 | - else | |
148 | - logger.level <= Logger::INFO and | |
149 | - OSDN::CLI._show_progress = true | |
150 | - fio = file.open | |
151 | - logger.info "Starting upload #{file}..." | |
152 | - finfo = api.create_release_file target_proj, target_package(rdir), target_release(rdir), fio, visibility: @visibility | |
153 | - fio.close | |
154 | - OSDN::CLI._show_progress = false | |
155 | - if digests.find { |type, dig| dig != finfo.send("digest_#{type}") } | |
156 | - logger.error "File digests are mismatch! Upload file #{file} may be broken! Please check." | |
157 | - else | |
158 | - logger.info "Upload complete." | |
159 | - end | |
160 | - end | |
161 | - $stdout.puts "New file '#{file}' has been uploaded; #{finfo.url}" | |
162 | - end | |
119 | + if err['status'] == 404 | |
120 | + logger.warn "Release ##{vars.release_id} has been deleted on server and local directory '#{rdir}' remains. You can delete the local directory or delete '#{rdir}/.osdn.vars' file to create a release again with new ID." | |
121 | + return false | |
163 | 122 | end |
123 | + raise e | |
164 | 124 | end |
125 | + else vars.release_id | |
126 | + logger.info "Createing new release '#{rdir.basename}'" | |
127 | + if @dry_run | |
128 | + rinfo = Hashie::Mash.new id: '(dry-run)', name: rdir.basename, url: '(dry-run)', files: [] | |
129 | + else | |
130 | + rinfo = api.create_release target_proj, target_package(rdir), rdir.basename, visibility: @visibility | |
131 | + update_variables rdir, release_id: rinfo.id | |
132 | + end | |
133 | + $stdout.puts "New release '#{rinfo.name}' has been created; #{rinfo.url}" | |
134 | + end | |
135 | + Pathname.glob(rdir + '*').sort.each do |file| | |
136 | + process_file(file, rdir, rinfo) | |
165 | 137 | end |
166 | 138 | end |
167 | 139 | |
168 | - def self.description | |
169 | - "Upload local file tree and create package/release implicitly." | |
170 | - end | |
140 | + def process_file(file, rdir, rinfo) | |
141 | + if file.directory? | |
142 | + logger.error "Skip direcotry #{file}" | |
143 | + return false | |
144 | + end | |
145 | + | |
146 | + vars = load_variables(rdir) | |
147 | + digests = nil | |
148 | + if !@force_digest && vars.local_file_info && | |
149 | + vars.local_file_info[file.basename.to_s] | |
150 | + finfo = vars.local_file_info[file.basename.to_s] | |
151 | + if finfo[:size] == file.size && finfo.mtime == file.mtime | |
152 | + digests = vars.local_file_info[file.basename.to_s].digests | |
153 | + end | |
154 | + end | |
155 | + | |
156 | + unless digests | |
157 | + logger.info "Calculating digest for #{file}..." | |
158 | + digests = { | |
159 | + sha256: hexdigest(Digest::SHA256, file), | |
160 | + sha1: hexdigest(Digest::SHA1, file), | |
161 | + md5: hexdigest(Digest::MD5, file), | |
162 | + } | |
163 | + update_variables rdir, {local_file_info: {file.basename.to_s => {digests: digests, mtime: file.mtime, size: file.size}}} | |
164 | + end | |
165 | + if remote_f = rinfo.files.find { |f| f.name == file.basename.to_s } | |
166 | + if digests.find { |type, dig| dig != remote_f.send("digest_#{type}") } | |
167 | + logger.error "#{file} was changed from remote file! Please delete remote file before uploading new one." | |
168 | + end | |
169 | + logger.info "Skip already uploaded file '#{file}'" | |
170 | + return | |
171 | + end | |
171 | 172 | |
173 | + logger.info "Uploading file #{file} (#{file.size} bytes)" | |
174 | + if @dry_run | |
175 | + finfo = Hashie::Mash.new id: '(dry-run)', url: '(dry-run)' | |
176 | + else | |
177 | + logger.level <= Logger::INFO and | |
178 | + OSDN::CLI._show_progress = true | |
179 | + fio = file.open | |
180 | + logger.info "Starting upload #{file}..." | |
181 | + finfo = api.create_release_file target_proj, target_package(rdir), target_release(rdir), fio, visibility: @visibility | |
182 | + fio.close | |
183 | + OSDN::CLI._show_progress = false | |
184 | + if digests.find { |type, dig| dig != finfo.send("digest_#{type}") } | |
185 | + logger.error "File digests are mismatch! Upload file #{file} may be broken! Please check." | |
186 | + else | |
187 | + logger.info "Upload complete." | |
188 | + end | |
189 | + end | |
190 | + $stdout.puts "New file '#{file}' has been uploaded; #{finfo.url}" | |
191 | + end | |
192 | + | |
172 | 193 | private |
173 | 194 | def target_proj |
174 | 195 | @target_proj and return @target_proj |