OSDN Git Service

Tiny update on message.
[osdn-codes/osdn-cli.git] / lib / osdn / cli / command / frs_upload.rb
1 module OSDN; module CLI; module Command
2   class FrsUpload < Base
3     def help
4       puts "#{$0} frs_upload [opts] [target_dir]"
5       puts "Options:"
6       puts "  -n --dry-run               Do noting (use with global -v to inspect)"
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)"
10       puts "  -v --visibility=<public|private|hidden>"
11       puts "                             Default visibility for newly created items"
12     end
13
14     def run
15       update_token
16       opts = GetoptLong.new(
17         [ '--dry-run', '-n', GetoptLong::NO_ARGUMENT ],
18         [ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ],
19         [ '--release', '-r', GetoptLong::REQUIRED_ARGUMENT ],
20         [ '--visibility', '-v', GetoptLong::REQUIRED_ARGUMENT ],
21       )
22       opts.each do |opt, arg|
23         case opt
24         when '--project'
25           arg.empty? or
26             @target_proj = arg
27         #when '--release'
28         #  arg.empty? or
29         #    @target_release = arg
30         #when '--package'
31         #  arg.empty? or
32         #    @target_package = arg
33         when '--visibility'
34           unless %w(public private hidden).member?(arg)
35             logger.fatal "Invalid visibility status: #{arg}"
36             exit
37           end
38           @visibility = arg
39         when '--dry-run'
40           @dry_run = true
41         end
42       end
43
44       @target_dir = Pathname.new(ARGV.shift || '.')
45       proj_info = api.get_project target_proj # check project existance
46
47       Pathname.glob(@target_dir+'*').sort.each do |pdir|
48         unless load_variables(pdir).package_id
49           logger.info "Createing new package '#{pdir.basename}'"
50           if @dry_run
51             pinfo = Hashie::Mash.new id: '(dry-run)', name: pdir.basename, url: '(dry-run)'
52           else
53             pinfo = api.create_package target_proj, pdir.basename, visibility: @visibility
54             update_variables pdir, package_id: pinfo.id
55           end
56           $stdout.puts "New package '#{pinfo.name}' has been created; #{pinfo.url}"
57         end
58
59         Pathname.glob(pdir + '*').sort.each do |rdir|
60           vars = load_variables(rdir)
61           rinfo = nil
62           if vars.release_id
63             rinfo = api.get_release target_proj, target_package(rdir), target_release(rdir)
64           else vars.release_id
65             logger.info "Createing new release '#{rdir.basename}'"
66             if @dry_run
67               rinfo = Hashie::Mash.new id: '(dry-run)', name: rdir.basename, url: '(dry-run)', files: []
68             else
69               rinfo = api.create_release target_proj, target_package(rdir), rdir.basename, visibility: @visibility
70               update_variables rdir, release_id: rinfo.id
71             end
72             $stdout.puts "New release '#{rinfo.name}' has been created; #{rinfo.url}"
73           end
74           
75           Pathname.glob(rdir + '*').sort.each do |file|
76             if file.directory?
77               logger.error "Skip direcotry #{file}"
78               next
79             end
80
81             logger.debug "Calculating digest for #{file}..."
82             digests = {
83               sha256: hexdigest(Digest::SHA256, file),
84               sha1:   hexdigest(Digest::SHA1, file),
85               md5:    hexdigest(Digest::MD5, file),
86             }
87             if remote_f = rinfo.files.find { |f| f.name == file.basename.to_s }
88               if digests.find { |type, dig| dig != remote_f.send("digest_#{type}") }
89                 logger.error "#{file} was changed from remote file! Please delete remote file before uploading new one."
90               end
91               logger.warn "Skip already uploaded file '#{file}'"
92             else
93               logger.info "Uploading file #{file} (#{file.size} bytes)"
94               if @dry_run
95                 finfo = Hashie::Mash.new id: '(dry-run)', url: '(dry-run)'
96               else
97                 logger.level <= Logger::INFO and
98                   OSDN::CLI._show_progress = true
99                 fio = file.open
100                 logger.info "Starting upload #{file}..."
101                 finfo = api.create_release_file target_proj, target_package(rdir), target_release(rdir), fio, visibility: @visibility
102                 fio.close
103                 OSDN::CLI._show_progress = false
104                 if digests.find { |type, dig| dig != finfo.send("digest_#{type}") }
105                   logger.error "File digests are mismatch! Upload file #{file} may be broken! Please check."
106                 else
107                   logger.info "Upload complete."
108                 end
109               end
110               $stdout.puts "New file '#{file}' has been uploaded; #{finfo.url}"
111             end
112           end
113         end
114       end
115     end
116
117     def self.description
118       "Upload local file tree and create package/release implicitly."
119     end
120
121     private
122     def target_proj
123       @target_proj and return @target_proj
124       vars = load_variables(@target_dir)
125       vars.project && !vars.project.empty? and
126         return vars.project
127       logger.fatal "No target project is specified."
128       exit
129     end
130
131     def target_package(dir)
132       @target_package and return @target_package
133       vars = load_variables(dir)
134       vars.package_id && !vars.package_id.to_s.empty? and
135         return vars.package_id
136       logger.fatal "No target package is specified."
137       exit
138     end
139
140     def target_release(dir)
141       @target_release and return @target_release
142       vars = load_variables(dir)
143       vars.release_id && !vars.release_id.to_s.empty? and
144         return vars.release_id
145       logger.fatal "No target release is specified."
146       exit
147     end
148
149     def api
150       OSDNClient::ProjectApi.new
151     end
152   end
153 end; end; end