OSDN Git Service

ca2b4e83b5d24186e383a43bcb50c81fea74a100
[osdn-codes/osdn-cli.git] / lib / osdn / cli / command / relfile.rb
1 require 'osdn/cli/command/frs_base'
2 require 'pathname'
3
4 module OSDN; module CLI; module Command
5   class Relfile < FrsBase
6     def help
7       puts "#{$0} relfile [opts] [list]"
8       puts "#{$0} relfile [opts] create <target-file> [target-files...]"
9       puts "#{$0} relfile [opts] update <numeric-file-id>"
10       puts "#{$0} relfile [opts] delete <numeric-file-id>"
11       puts "Options:"
12       puts "  -f --format=<pretty|json>  Set output format"
13       puts "  -p --project=<project>     Target project (numeric id or name)"
14       puts "     --package=<package-id>  Target package (numeric id)"
15       puts "     --release=<release-id>  Target release (numeric id)"
16       puts "  -v --visibility=<public|private|hidden>"
17       puts "      --force-digest         Calc local file digest forcely"
18       puts "      --progress             Force to show upload progress"
19       puts "      --no-progress          Force to hide upload progress"
20     end
21
22     def self.description
23       "Manipulate frs files of project"
24     end
25
26     def process_options
27       opts = GetoptLong.new(
28         [ '--format', '-f', GetoptLong::REQUIRED_ARGUMENT ],
29         [ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ],
30         [ '--package', GetoptLong::REQUIRED_ARGUMENT ],
31         [ '--release', GetoptLong::REQUIRED_ARGUMENT ],
32         [ '--visibility', '-v', GetoptLong::REQUIRED_ARGUMENT ],
33         [ '--force-digest', GetoptLong::NO_ARGUMENT],
34         [ '--progress', GetoptLong::NO_ARGUMENT],
35         [ '--no-progress', GetoptLong::NO_ARGUMENT],
36       )
37       opts.each do |opt, arg|
38         case opt
39         when '--format'
40           arg == 'json' and
41             self.format = arg
42         when '--project'
43           arg.empty? or
44             @target_proj = arg
45         when '--package'
46           arg.empty? or
47             @target_package = arg
48         when '--release'
49           arg.empty? or
50             @target_release = arg
51         when '--force-digest'
52           @force_digest = true
53         when '--visibility'
54           unless %w(public private hidden).member?(arg)
55             logger.fatal "Invalid visibility status: #{arg}"
56             exit
57           end
58           @visibility = arg
59         when '--progress'
60           @show_progress = true
61         when '--no-progress'
62           @show_progress = false
63         end
64       end
65     end
66     
67     def list
68       release = api.get_release target_proj, target_package, target_release
69       list = release.files
70       if format == 'json'
71         puts list.map{|i| i.to_hash}.to_json
72       else
73         list.each do |f|
74           puts format_file(f)
75         end
76       end
77     end
78
79     def create
80       if ARGV.empty? || ARGV.first == ""
81         logger.fatal "Target filename is missing."
82         help
83         return
84       end
85
86       ARGV.each do |f|
87         create_one(f)
88       end
89     end
90
91     def create_one(filename)
92       file = Pathname('.') + filename
93       logger.debug "Calculating digest for #{file}..."
94
95       vars = load_variables(file.dirname)
96       digests = nil
97       if !@force_digest && vars.local_file_info &&
98          vars.local_file_info[file.basename.to_s]
99         finfo = vars.local_file_info[file.basename.to_s]
100         if finfo[:size] == file.size && finfo.mtime == file.mtime
101           digests = vars.local_file_info[file.basename.to_s].digests
102         end
103       end
104
105       unless digests
106         logger.info "Calculating digest for #{file}..."
107         digests = {
108           sha256: hexdigest(Digest::SHA256, file),
109           sha1:   hexdigest(Digest::SHA1, file),
110           md5:    hexdigest(Digest::MD5, file),
111         }
112         update_variables file.dirname, {local_file_info: {file.basename.to_s => {digests: digests, mtime: file.mtime, size: file.size}}}
113       end
114
115       fio = file.open
116       logger.level <= Logger::INFO && @show_progress != false || @show_progress and
117         OSDN::CLI._show_progress = true
118       logger.info "Starting upload #{file}..."
119       f = api.create_release_file target_proj, target_package, target_release, fio, visibility: @visibility
120       fio.close
121       OSDN::CLI._show_progress = false
122       if digests.find { |type, dig| dig != f.send("digest_#{type}") }
123         logger.error "File digests are mismatch! Upload file #{file} may be broken! Please check."
124       else
125         logger.info "Upload complete."
126       end
127       puts format_file(f)
128     end
129
130     def update
131       target_id = ARGV.shift
132       if !target_id
133         logger.fatal "Target file ID is missing."
134         help
135         return
136       end
137       if @visibility.nil?
138         logger.fatal "Visibility status is missing. Use '-v <public|private|hidden>'."
139         return
140       end
141       f = api.update_release_file target_proj, target_package, target_release, target_id, visibility: @visibility
142       logger.info "file #{target_id} has been updated."
143       puts format_file(f)
144     end
145
146     def delete
147       target_id = ARGV.shift
148       if !target_id
149         logger.fatal "Target file ID is missing."
150         help
151         return
152       end
153       f = api.delete_release_file target_proj, target_package, target_release, target_id
154       logger.info "file #{target_id} has been deleted."
155     end
156   end
157 end; end; end