1 module OSDN; module CLI; module Command
3 attr_accessor :target_proj, :visibility, :force_digest, :dry_run, :show_progress
6 puts "#{$0} frs_upload [opts] [target_dir]"
8 puts " -n --dry-run Do noting (use with global -v to inspect)"
9 puts " -p --project=<project> Target project (numeric id or name)"
10 puts " --package=<package-id> Target package (numeric id)"
11 puts " --release=<release-id> Target release (numeric id)"
12 puts " -v --visibility=<public|private|hidden>"
13 puts " Default visibility for newly created items"
14 puts " --force-digest Calc local file digest forcely"
15 puts " --progress Force to show upload progress"
16 puts " --no-progress Force to hide upload progress"
17 puts " --bwlimit=RATE Limit bandwidth (in KB)"
22 opts = GetoptLong.new(
23 [ '--dry-run', '-n', GetoptLong::NO_ARGUMENT ],
24 [ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ],
25 [ '--package', GetoptLong::REQUIRED_ARGUMENT ],
26 [ '--release', GetoptLong::REQUIRED_ARGUMENT ],
27 [ '--visibility', '-v', GetoptLong::REQUIRED_ARGUMENT ],
28 [ '--force-digest', GetoptLong::NO_ARGUMENT],
29 [ '--progress', GetoptLong::NO_ARGUMENT],
30 [ '--no-progress', GetoptLong::NO_ARGUMENT],
31 [ '--bwlimit', GetoptLong::REQUIRED_ARGUMENT ],
33 opts.each do |opt, arg|
45 unless %w(public private hidden).member?(arg)
46 logger.fatal "Invalid visibility status: #{arg}"
57 @show_progress = false
60 OSDN::CLI._rate_limit = arg.to_i * 1024
64 (ARGV.empty? ? ['.'] : ARGV).each do |d|
65 @target_dir = Pathname.new(d)
71 proj_info = api.get_project target_proj # check project existance
73 vars = load_variables(@target_dir)
74 parent_vars = load_variables(@target_dir.parent)
76 if @target_release || vars.release_id ||
77 parent_vars.package_id && !vars.release_id # new release case...
78 process_release(@target_dir)
79 elsif @target_package || vars.package_id
80 process_package(@target_dir)
82 Pathname.glob(@target_dir+'*').sort.each do |pdir|
89 "Upload local file tree and create package/release implicitly."
92 def process_package(pdir)
93 if cur_pkgid = load_variables(pdir).package_id
94 # check package existance on server
96 api.get_package target_proj, target_package(pdir)
97 rescue OSDNClient::ApiError => e
99 err = JSON.parse(e.response_body)
103 if err['status'] == 404
104 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."
110 logger.info "Createing new package '#{pdir.basename}'"
112 pinfo = Hashie::Mash.new id: '(dry-run)', name: pdir.basename, url: '(dry-run)'
114 pinfo = api.create_package target_proj, pdir.basename, visibility: @visibility
115 update_variables pdir, package_id: pinfo.id
117 $stdout.puts "New package '#{pinfo.name}' has been created; #{pinfo.url}"
120 Pathname.glob(pdir + '*').sort.each do |rdir|
121 process_release(rdir)
125 def process_release(rdir)
127 logger.warn "Skip normal file '#{rdir}' in release level"
131 vars = load_variables(rdir)
135 rinfo = api.get_release target_proj, target_package(rdir), target_release(rdir)
136 rescue OSDNClient::ApiError => e
138 err = JSON.parse(e.response_body)
142 if err['status'] == 404
143 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."
149 logger.info "Createing new release '#{rdir.basename}'"
151 rinfo = Hashie::Mash.new id: '(dry-run)', name: rdir.basename, url: '(dry-run)', files: []
153 rinfo = api.create_release target_proj, target_package(rdir), rdir.basename, visibility: @visibility
154 update_variables rdir, release_id: rinfo.id
156 $stdout.puts "New release '#{rinfo.name}' has been created; #{rinfo.url}"
158 Pathname.glob(rdir + '*').sort.each do |file|
159 process_file(file, rdir, rinfo)
163 def process_file(file, rdir, rinfo)
165 logger.error "Skip direcotry #{file}"
169 filecmd = Relfile.new logger
170 [:target_proj, :visibility, :force_digest, :show_progress].each do |opt|
171 filecmd.send "#{opt}=", send(opt)
173 filecmd.target_package = target_package(rdir)
174 filecmd.target_release = target_release(rdir)
175 filecmd.calc_file_digest(file)
177 vars = load_variables(rdir)
178 digests = vars.local_file_info[file.basename.to_s].digests
180 if remote_f = rinfo.files.find { |f| f.name == file.basename.to_s }
181 if remote_f.size != file.size || digests.find { |type, dig| rd = remote_f.send("digest_#{type}"); rd && rd != '' && dig != rd }
182 logger.error "#{file} was changed from remote file! Please delete remote file before uploading new one."
184 logger.info "Skip already uploaded file '#{file}'"
189 logger.info "Uploading file #{file} (#{file.size} bytes)"
191 finfo = Hashie::Mash.new id: '(dry-run)', url: '(dry-run)'
193 finfo = filecmd.create_one file
195 $stdout.puts "New file '#{file}' has been uploaded; #{finfo.url}"
200 @target_proj and return @target_proj
201 vars = load_variables(@target_dir)
202 vars.project && !vars.project.empty? and
204 logger.fatal "No target project is specified."
208 def target_package(dir)
209 @target_package and return @target_package
210 vars = load_variables(dir)
211 vars.package_id && !vars.package_id.to_s.empty? and
212 return vars.package_id
213 logger.fatal "No target package is specified."
217 def target_release(dir)
218 @target_release and return @target_release
219 vars = load_variables(dir)
220 vars.release_id && !vars.release_id.to_s.empty? and
221 return vars.release_id
222 logger.fatal "No target release is specified."
227 OSDNClient::ProjectApi.new