wooga_wooget 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.travis.yml +20 -0
  4. data/Gemfile +3 -0
  5. data/Licence.md +21 -0
  6. data/README.md +48 -0
  7. data/Rakefile +80 -0
  8. data/bin/wooget +5 -0
  9. data/lib/wooget.rb +57 -0
  10. data/lib/wooget/build/build_info.rb +64 -0
  11. data/lib/wooget/build/builder.rb +285 -0
  12. data/lib/wooget/cli.rb +293 -0
  13. data/lib/wooget/nuget.rb +96 -0
  14. data/lib/wooget/paket.rb +81 -0
  15. data/lib/wooget/project.rb +42 -0
  16. data/lib/wooget/releasing.rb +112 -0
  17. data/lib/wooget/template/files/README.md.erb +20 -0
  18. data/lib/wooget/template/files/RELEASE_NOTES.md.erb +2 -0
  19. data/lib/wooget/template/files/assemblyinfo.erb +36 -0
  20. data/lib/wooget/template/files/class.erb +15 -0
  21. data/lib/wooget/template/files/csproj.erb +56 -0
  22. data/lib/wooget/template/files/gitignore.erb +13 -0
  23. data/lib/wooget/template/files/metafile.cs.erb +11 -0
  24. data/lib/wooget/template/files/paket.binary.template.erb +17 -0
  25. data/lib/wooget/template/files/paket.dependencies.erb +13 -0
  26. data/lib/wooget/template/files/paket.references.erb +2 -0
  27. data/lib/wooget/template/files/paket.template.erb +22 -0
  28. data/lib/wooget/template/files/sln.erb +32 -0
  29. data/lib/wooget/template/files/test_file.erb +19 -0
  30. data/lib/wooget/template/files/tests_assemblyinfo.erb +36 -0
  31. data/lib/wooget/template/files/tests_csproj.erb +67 -0
  32. data/lib/wooget/template/files/unity_paket.dependencies.erb +12 -0
  33. data/lib/wooget/template/unity.rb +73 -0
  34. data/lib/wooget/template/visual_studio.rb +56 -0
  35. data/lib/wooget/template/wooget_conf.json +13 -0
  36. data/lib/wooget/third_party/paket.bootstrapper.exe +0 -0
  37. data/lib/wooget/third_party/paket.exe +0 -0
  38. data/lib/wooget/third_party/paket.targets +36 -0
  39. data/lib/wooget/third_party/paket.unity3d.bootstrapper.exe +0 -0
  40. data/lib/wooget/third_party/paket.unity3d.exe +0 -0
  41. data/lib/wooget/util/build_error.rb +8 -0
  42. data/lib/wooget/util/misc.rb +91 -0
  43. data/lib/wooget/util/package_list_formatter.rb +59 -0
  44. data/lib/wooget/version.rb +22 -0
  45. data/tests/nuget_feed.xml +3439 -0
  46. data/tests/nuget_package.xml +49 -0
  47. data/tests/nuget_test.rb +27 -0
  48. data/tests/package_test.rb +72 -0
  49. data/tests/unity_test.rb +12 -0
  50. data/wiki/bootstrap.png +0 -0
  51. data/wiki/compiling.png +0 -0
  52. data/wiki/create.png +0 -0
  53. data/wiki/install.png +0 -0
  54. data/wiki/list.png +0 -0
  55. data/wiki/monodevelop.png +0 -0
  56. data/wiki/release.png +0 -0
  57. data/wiki/stupidmenu.png +0 -0
  58. data/wooget.gemspec +33 -0
  59. metadata +244 -0
data/lib/wooget/cli.rb ADDED
@@ -0,0 +1,293 @@
1
+ require 'thor'
2
+ require 'fileutils'
3
+ require 'json'
4
+ require 'pathname'
5
+ require 'activesupport/json_encoder'
6
+ module Wooget
7
+ class CLI < Thor
8
+ include Thor::Actions
9
+ class_option :verbose, :desc => "Spit out tons of logging info", :aliases => "-v", :type => :boolean
10
+ class_option :quiet, :desc => "Suppress stdout", :aliases => "-q", :type => :boolean, default: false
11
+ class_option :path, desc: "Path to the project you want to install things into", default: Dir.pwd
12
+
13
+
14
+ def initialize *args
15
+ super
16
+
17
+ Wooget.log.level = Logger::Severity::DEBUG if self.options[:verbose]
18
+ Wooget.repos[:default] = self.options[:repo] if self.options[:repo]
19
+ end
20
+
21
+ desc "create PACKAGE_NAME", "create a new package"
22
+ option :visual_studio, desc: "Should visual studio files (.csproj .sln) be generated?", type: :boolean, default: true
23
+ option :tests, desc: "Should test project be generated?", type: :boolean, default: true
24
+ option :author, desc: "name to use for author field of nupkg"
25
+
26
+ def create package_name
27
+ proj = Project.new
28
+ proj.create package_name, options
29
+ end
30
+
31
+ desc "build", "build the packages in the current dir"
32
+ option :version, desc:"Version number to prepend to release notes", type: :string, required: true
33
+ option :output, desc: "Dir to place built packages", type: :string, default: "bin"
34
+ option :release_notes, desc: "Release notes to include in the package", type: :string, default: ""
35
+ option :native, desc: "Invoke native build functionality", type: :boolean, default: true
36
+ def build
37
+ package_release_checks
38
+
39
+ p "Preinstall before build"
40
+ invoke "install", [], quiet:true, path:get_path
41
+
42
+ p "Running tests"
43
+ invoke "test", [], path:get_path
44
+
45
+ #templates refs have to be relative to the working dir / project root for paket.exe
46
+ path = Pathname.new(options[:path])
47
+ templates = Dir.glob(File.join(options[:path],"**/*paket.template"))
48
+ templates.map! { |t| Pathname.new(t).relative_path_from(path).to_s}
49
+
50
+ build_options = {
51
+ output_dir: options[:output],
52
+ version:options[:version],
53
+ release_notes: options[:release_notes],
54
+ templates: templates,
55
+ path: options[:path],
56
+ native: options[:native]
57
+ }
58
+
59
+ built_packages = invoke "wooget:packager:build", [], build_options
60
+
61
+ p "#{built_packages.join " & "} built to #{File.expand_path File.join(options[:path],options[:output])}" if built_packages
62
+ end
63
+
64
+ option :repo, desc: "Which repo to use"
65
+ option :push, desc: "Should built package be pushed to repo", default: true, type: :boolean
66
+ option :confirm, desc: "Ask for confirmation before pushing", default: true, type: :boolean
67
+ option :output, desc: "Dir to place built packages", type: :string, default: "bin"
68
+ option :git, desc: "Use git functionality", type: :boolean, default: true
69
+ option :native, desc: "Invoke native build functionality", type: :boolean, default: true
70
+ desc "release", "release package in current dir"
71
+
72
+ def release
73
+ package_release_checks
74
+
75
+ released_packages = invoke "wooget:packager:release", [], options
76
+
77
+ p "#{released_packages.join " & "} released successfully" if released_packages
78
+ end
79
+
80
+ option :repo, desc: "Which repo to use"
81
+ option :push, desc: "Should built package be pushed to repo", default: true, type: :boolean
82
+ option :confirm, desc: "Ask for confirmation before pushing", default: true, type: :boolean
83
+ option :output, desc: "Dir to place built packages", type: :string, default: "bin"
84
+ option :git, desc: "Use git functionality", type: :boolean, default: true
85
+ option :native, desc: "Invoke native build functionality", type: :boolean, default: true
86
+ desc "prerelease", "prerelease package in current dir"
87
+
88
+ def prerelease
89
+ package_release_checks
90
+
91
+ released_packages = invoke "wooget:packager:prerelease", [], options
92
+
93
+ p "#{released_packages.join " & "} prereleased successfully" if released_packages
94
+ end
95
+
96
+ desc "test", "run package tests in mono"
97
+
98
+ def test
99
+ unless Util.is_a_wooget_package_dir(options[:path]) and Dir.exists?(File.join(options[:path],"tests"))
100
+ Wooget.log.error "Can't find a wooget package dir with tests at #{options[:path]}"
101
+ return
102
+ end
103
+
104
+ slns = Dir.glob(File.join(options[:path],"/**/*.sln"))
105
+ sln = slns.select{ |d| not Wooget::Util.is_a_unity_project_dir(File.dirname(d))}.first
106
+
107
+ if sln.nil? or sln.empty?
108
+ Wooget.log.error "Can't find sln file for building test artifacts"
109
+ return
110
+ end
111
+
112
+ nunit = Dir.glob(File.join(options[:path],"/**/nunit-console.exe")).first
113
+ if nunit.nil? or nunit.empty?
114
+ Wooget.log.error "Can't find nunit-console for running tests"
115
+ return
116
+ end
117
+
118
+
119
+ Dir.mktmpdir do |tmp_dir|
120
+ p "Building test assembly.."
121
+ stdout, status = Util.run_cmd("xbuild #{File.expand_path(sln)} /t:Rebuild /p:RestorePackages='False' /p:Configuration='Release' /p:OutDir='#{tmp_dir}/'") { |log| Wooget.no_status_log log}
122
+ raise BuildError, stdout.join unless status == 0
123
+
124
+ Dir[File.join(tmp_dir, "*Tests*.dll")].each do |assembly|
125
+ _, status = Util.run_cmd("mono #{nunit} #{assembly} -nologo -labels -noshadow") { |log| p log}
126
+ p "Exit Status - #{status}"
127
+ end
128
+ end
129
+ end
130
+
131
+ desc "paket ARGS", "call bundled version of paket and pass args"
132
+
133
+ def paket *args
134
+ Wooget::Paket.execute(args.join(" "))
135
+ end
136
+
137
+ desc "paket_unity3d ARGS", "call bundled version of paket.unity3d and pass args"
138
+
139
+ def paket_unity3d *args
140
+ Wooget::Paket.unity3d_execute(args.join(" "))
141
+ end
142
+
143
+ option :force, desc: "Forces the download and reinstallation of all packages.", aliases: "-f", type: :boolean, default: false
144
+ desc "install", "install packages into this unity project"
145
+ def install package=nil
146
+ load_config
147
+
148
+ if Util.is_a_unity_project_dir(options[:path]) or Util.is_a_wooget_package_dir(options[:path])
149
+ if package and Util.is_a_unity_project_dir(options[:path])
150
+ invoke "wooget:unity:install", [package], options
151
+ end
152
+
153
+ Paket.install options
154
+ else
155
+ abort "Project not found at #{options[:path]}"
156
+ end
157
+ p "Installed!"
158
+ end
159
+
160
+ option :force, desc: "Forces the download and reinstallation of all packages.", aliases: "-f", type: :boolean, default: false
161
+ desc "update", "update packages into this unity project"
162
+ def update package=nil
163
+ load_config
164
+
165
+ if Util.is_a_unity_project_dir(options[:path]) or Util.is_a_wooget_package_dir(options[:path])
166
+ Paket.update package, options
167
+ else
168
+ abort "Project not found at #{options[:path]}"
169
+ end
170
+ p "Updated!"
171
+ end
172
+
173
+ desc "bootstrap", "setup environment / project for wooget usage"
174
+ def bootstrap
175
+ assert_dependencies
176
+ p "Dependencies OK"
177
+ load_config
178
+ p "Config OK"
179
+
180
+ if Util.is_a_unity_project_dir options[:path]
181
+ p "Unity project detected - Checking setup"
182
+ invoke "wooget:unity:bootstrap", [], options
183
+ end
184
+ end
185
+
186
+ option :repos, desc: "Which repos to list", type: :array, default: ["main", "universe","legacy","public"]
187
+ option :format, desc: "What format to output results", type: :string, enum: ["shell","json"], default: "shell"
188
+ option :show_binary, desc: "Display binary packages in output", type: :boolean, default: false
189
+ desc "list", "list available packages + version"
190
+ def list package_id=nil
191
+ load_config
192
+
193
+ if package_id
194
+ p PackageListFormatter.format_package package_list_by_repo, options[:format], package_id
195
+ else
196
+ p PackageListFormatter.format_list package_list_by_repo, options[:format], options[:show_binary]
197
+ end
198
+ end
199
+
200
+ option :repos, desc: "Which repos to search", type: :array, default: ["main", "universe","legacy"]
201
+ option :format, desc: "What format to output results", type: :string, enum: ["shell","json"], default: "shell"
202
+ option :show_binary, desc: "Display binary packages in output", type: :boolean, default: false
203
+ desc "search", "search packages by a regex"
204
+ def search pattern
205
+ load_config
206
+
207
+ packages_by_repo = package_list_by_repo pattern
208
+ p PackageListFormatter.format_list packages_by_repo, options[:format], options[:show_binary]
209
+ end
210
+
211
+ private
212
+ def package_list_by_repo(match_pattern=nil)
213
+ packages_by_repo = {}
214
+ packages_by_repo_lock = Mutex.new
215
+
216
+ threads = options[:repos].map do |repo|
217
+ Thread.new do
218
+ url = Wooget.repos[repo] || Wooget.repos[repo.to_sym]
219
+ raise RepoError, "Can't find a repository with name '#{repo}' in the configuration" unless url
220
+
221
+ nuget = Nuget.new
222
+ packages = nuget.invoke "packages", [], repo_url:url
223
+ packages = packages.select { |pkg| pkg.package_id.downcase.match(match_pattern.downcase) } unless match_pattern.nil?
224
+ packages_by_repo_lock.synchronize { packages_by_repo[repo] = packages}
225
+ end
226
+ end
227
+
228
+ threads.each {|t| t.join}
229
+ packages_by_repo
230
+ end
231
+
232
+
233
+ no_commands do
234
+ def load_config
235
+ config_location = File.expand_path(File.join("~", ".wooget"))
236
+ unless File.exists? config_location
237
+ Wooget.log.info "Creating default config at #{config_location}"
238
+
239
+ default_config = File.expand_path(File.join(File.dirname(__FILE__), "template", "wooget_conf.json"))
240
+ FileUtils.cp(default_config, config_location)
241
+ end
242
+
243
+ config = JSON.parse(File.read(config_location), symbolize_names: true)
244
+
245
+ Wooget.credentials.merge! config[:credentials]
246
+ Wooget.repos.merge! config[:repos]
247
+
248
+ if config[:repos][:default]
249
+ Wooget.repos[:default] = config[:repos][:default]
250
+ end
251
+
252
+ #set default repo to whatever was passed on commandline (if anything)
253
+ if options[:repo]
254
+ overridden_repo = Wooget.repos[options[:repo]] || Wooget.repos[options[:repo].to_sym]
255
+ abort "Repo '#{options[:repo]}' not found in conf - options are #{Wooget.repos.keys.join(", ")}" unless overridden_repo
256
+
257
+ Wooget.repos[:default] = overridden_repo
258
+ end
259
+
260
+ Wooget.log.debug "Acting as #{Wooget.credentials[:username]}"
261
+ Wooget.log.debug "Default repo is #{Wooget.repo}"
262
+ end
263
+ end
264
+
265
+ private
266
+
267
+
268
+ def assert_package_dir
269
+ abort "#{ get_path} doesn't appear to be a wooget package dir" unless Util.is_a_wooget_package_dir get_path
270
+ end
271
+
272
+ def get_path
273
+ path = Pathname.new(options[:path])
274
+ path.absolute? ? path : File.join(Dir.pwd, options[:path])
275
+ end
276
+
277
+ def assert_dependencies
278
+ %w( mono ).each do |dep|
279
+ `type #{dep}`
280
+ abort "Couldn't find #{dep} - please install!" unless $?.exitstatus == 0
281
+ end
282
+ end
283
+
284
+ def package_release_checks
285
+ assert_package_dir
286
+ load_config
287
+ end
288
+
289
+ def p msg
290
+ say msg unless options[:quiet]
291
+ end
292
+ end
293
+ end
@@ -0,0 +1,96 @@
1
+ require 'ostruct'
2
+ require 'oga'
3
+ require 'curb'
4
+
5
+ module Wooget
6
+ class Nuget < Thor
7
+ option :repo_url, desc: "url to the repo", required: true
8
+ desc "packages", "get packages for a repo"
9
+
10
+ def packages
11
+ Wooget.log.info "Fetching package list for #{options[:repo_url]} ..."
12
+
13
+ url = ""
14
+ if options[:repo_url] == Wooget.repos[:public]
15
+ url = "https://packages.nuget.org/api/v2/Search?searchTerm=%27wooget%27"
16
+ else
17
+ url = options[:repo_url] + '/Search?$orderby=Id&$filter=IsLatestVersion&searchterm='
18
+ end
19
+
20
+ c = Curl::Easy.new(url)
21
+ c.username = Wooget.credentials[:username]
22
+ c.password = Wooget.credentials[:password]
23
+
24
+ c.perform
25
+
26
+ Nuget.from_xml c.body_str
27
+ end
28
+
29
+ def self.from_xml file
30
+ if file.is_a? String and File.exists? file
31
+ file = File.open(file)
32
+ end
33
+
34
+ doc = Oga.parse_xml(file)
35
+
36
+ entries = doc.css "entry"
37
+ entries.map do |e|
38
+ id = e.at_css("title").text()
39
+ url = e.at_css("id").text()
40
+ props_xml = e.at_css("properties").children
41
+ properties = props_xml.inject({}) do |hsh, node|
42
+ hsh[node.name] = node.text() if node.respond_to? :name
43
+ hsh
44
+ end
45
+
46
+ Package.new id, url, properties
47
+ end
48
+ end
49
+ end
50
+
51
+ class Package
52
+ attr_reader :properties, :url, :package_id
53
+
54
+ attr_reader :id, :version, :normalized_version, :authors, :copyright, :created, :dependencies, :description, :download_count
55
+ attr_reader :gallery_details_url, :icon_url, :is_latest_version, :is_absolute_latest_version, :is_prerelease, :language, :last_updated
56
+ attr_reader :published, :package_hash, :package_hash_algorithm, :package_size, :project_url, :report_abuse_url, :release_notes
57
+ attr_reader :require_license_acceptance, :license_url, :summary, :tags
58
+
59
+ attr_accessor :has_binary, :is_binary
60
+
61
+ def initialize package_id, url, properties
62
+ @package_id = package_id
63
+ @url = url
64
+ @properties = properties || {}
65
+
66
+ apply_properties
67
+ end
68
+
69
+ #
70
+ # discern between source and binary packages
71
+ def self.process_binary_packages(packages)
72
+ packages.each do |package|
73
+ package.is_binary = (package.package_id =~ /Binary/ or packages.any? { |p| p.package_id == package.package_id + ".Source" })
74
+ package.has_binary = packages.any? do |p|
75
+ (p.package_id != package.package_id and p.package_id == package.package_id.chomp(".Source"))\
76
+ or p.package_id == package.package_id + ".Binary"
77
+ end
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ def apply_properties
84
+ @properties.each do |k, v|
85
+ if self.respond_to? "#{k.snake_case}".to_sym
86
+
87
+ v = true if v == "true"
88
+ v = false if v == "false"
89
+
90
+ instance_variable_set "@#{k.snake_case}".to_sym, v
91
+ end
92
+ end
93
+ @dependencies = @dependencies.split("|") if @dependencies
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,81 @@
1
+ module Wooget
2
+ class Paket
3
+ @@paket_path = File.expand_path(File.join(__FILE__, "..", "third_party", "paket.exe"))
4
+ @@unity3d_path = File.expand_path(File.join(__FILE__, "..", "third_party", "paket.unity3d.exe"))
5
+
6
+ def self.execute args
7
+ cmd = "mono #{ @@paket_path} #{args}"
8
+ Wooget.log.debug "Running #{cmd}"
9
+
10
+ exec cmd
11
+ end
12
+
13
+ def self.unity3d_execute args
14
+ cmd = "mono #{@@unity3d_path} #{args}"
15
+ Wooget.log.debug "Running #{cmd}"
16
+
17
+ exec cmd
18
+ end
19
+
20
+ def self.install options={}
21
+ options[:path] ||= Dir.pwd
22
+
23
+ commands = ["#{env_vars} mono #{@@paket_path} install #{"--force" if options[:force]}"]
24
+ commands << "#{env_vars} mono #{@@unity3d_path} install" if Util.is_a_unity_project_dir(options[:path])
25
+
26
+ commands.each do |cmd|
27
+ reason, exitstatus = Util.run_cmd(cmd, options[:path]) { |log| Wooget.no_status_log log }
28
+ unless exitstatus == 0
29
+ Wooget.log.error "Install failed:\n #{reason}"
30
+ break
31
+ end
32
+ end
33
+ end
34
+
35
+ def self.update package=nil, options={}
36
+ options[:path] ||= Dir.pwd
37
+
38
+ commands = ["#{env_vars} mono #{@@paket_path} update #{"nuget #{package}" if package} #{"--force" if options[:force]}"]
39
+ commands << "#{env_vars} mono #{@@unity3d_path} install" if Util.is_a_unity_project_dir(options[:path])
40
+
41
+ commands.each do |cmd|
42
+ reason, exitstatus = Util.run_cmd(cmd, options[:path]) { |log| Wooget.no_status_log log }
43
+ unless exitstatus == 0
44
+ Wooget.log.error "Update failed:\n #{reason}"
45
+ break
46
+ end
47
+ end
48
+ end
49
+
50
+ def self.env_vars
51
+ "USERNAME=#{Wooget.credentials[:username]} PASSWORD=#{Wooget.credentials[:password]}"
52
+ end
53
+
54
+ def self.installed? project_path, package
55
+ abort "Not a valid paket dir - #{project_path}" unless Util.is_a_unity_project_dir(project_path) or Util.is_a_wooget_package_dir(project_path)
56
+
57
+ lock_file = File.join(project_path, "paket.lock")
58
+ return false unless File.exists? lock_file
59
+
60
+ File.open(lock_file).read.lines.any? { |l| l =~ /\s*#{package}\s+/ }
61
+ end
62
+
63
+ def self.should_generate_unity3d_references? path=Dir.pwd
64
+ #if the references file doesnt exist, or it does exist and
65
+ # it contains the automanage tag then we can rewrite it
66
+ auto_manage_tag = "[!automanage!]"
67
+ !File.exists?(File.join(path, "paket.unity3d.references")) or (Util.file_contains? File.join(path, "paket.dependencies"), auto_manage_tag)
68
+ end
69
+
70
+ def self.pack options
71
+ pack_cmd = "#{env_vars} mono #{@@paket_path} pack output #{options[:output]} version #{options[:version]} releaseNotes \"#{options[:release_notes]}\""
72
+ Util.run_cmd(pack_cmd, options[:path] || Dir.pwd) { |log| Wooget.no_status_log log }
73
+ end
74
+
75
+ def self.push auth, url, package
76
+ push_cmd = "#{env_vars} nugetkey=#{auth} mono #{@@paket_path} push url #{url} file #{package}"
77
+ Util.run_cmd(push_cmd) { |log| Wooget.no_status_log log }
78
+ end
79
+
80
+ end
81
+ end