1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Helpful features about packages
20 redef class ToolContext
22 var opt_expand
= new OptionBool("Move singleton packages to their own directory", "--expand")
25 var opt_gen_ini
= new OptionBool("Generate package.ini files", "--gen-ini")
28 var opt_force
= new OptionBool("Force update of existing files", "-f", "--force")
30 # README handling phase
31 var readme_phase
: Phase = new ReadmePhase(self, null)
35 option_context
.add_option
(opt_expand
, opt_force
)
36 option_context
.add_option
(opt_gen_ini
)
40 private class ReadmePhase
43 redef fun process_mainmodule
(mainmodule
, mmodules
) do
44 var mpackages
= extract_mpackages
(mmodules
)
45 for mpackage
in mpackages
do
47 # Fictive and buggy packages are ignored
48 if not mpackage
.has_source
then
49 toolcontext
.warning
(mpackage
.location
, "no-source",
50 "Warning: `{mpackage}` has no source file")
55 if toolcontext
.opt_expand
.value
and not mpackage
.is_expanded
then
56 var path
= mpackage
.expand
57 toolcontext
.info
("{mpackage} moved to {path}", 0)
59 if not mpackage
.is_expanded
then
60 toolcontext
.warning
(mpackage
.location
, "no-dir",
61 "Warning: `{mpackage}` has no package directory")
66 if toolcontext
.opt_gen_ini
.value
then
67 if not mpackage
.has_ini
or toolcontext
.opt_force
.value
then
68 var path
= mpackage
.gen_ini
69 toolcontext
.info
("generated INI file `{path}`", 0)
75 # Extract the list of packages from the mmodules passed as arguments
76 fun extract_mpackages
(mmodules
: Collection[MModule]): Collection[MPackage] do
77 var mpackages
= new ArraySet[MPackage]
78 for mmodule
in mmodules
do
79 var mpackage
= mmodule
.mpackage
80 if mpackage
== null then continue
81 mpackages
.add mpackage
89 # Expand `self` in its own directory
90 private fun expand
: String do
91 assert not is_expanded
93 var ori_path
= package_path
.as(not null)
94 var new_path
= ori_path
.dirname
/ name
97 sys
.system
"mv {ori_path} {new_path / name}.nit"
99 var ini_file
= "{new_path}.ini"
100 if ini_file
.file_exists
then
101 sys
.system
"mv {new_path}.ini {new_path}/package.ini"
107 private var maintainer
: nullable String is lazy
do
108 return git_exec
("git shortlog -esn . | head -n 1 | sed 's/\\s*[0-9]*\\s*//'")
111 private var contributors
: Array[String] is lazy
do
112 var contribs
= git_exec
("git shortlog -esn . | head -n -1 | " +
113 "sed 's/\\s*[0-9]*\\s*//'")
114 if contribs
== null then return new Array[String]
115 return contribs
.split
("\n")
118 private var git_url
: nullable String is lazy
do
119 var git
= git_exec
("git remote get-url origin")
120 if git
== null then return null
121 git
= git
.replace
("git@github.com:", "https://github.com/")
122 git
= git
.replace
("git@gitlab.com:", "https://gitlab.com/")
126 private var git_dir
: nullable String is lazy
do
127 return git_exec
("git rev-parse --show-prefix")
130 private var browse_url
: nullable String is lazy
do
132 if git
== null then return null
133 var browse
= git
.replace
(".git", "")
135 if dir
== null or dir
.is_empty
then return browse
136 return "{browse}/tree/master/{dir}"
139 private var homepage_url
: nullable String is lazy
do
141 if git
== null then return null
142 # Special case for nit files
143 if git
.has_suffix
("/nit.git") then
144 return "http://nitlanguage.org"
146 return git
.replace
(".git", "")
149 private var issues_url
: nullable String is lazy
do
151 if git
== null then return null
152 return "{git.replace(".git", "")}/issues"
155 private var license
: nullable String is lazy
do
157 if git
== null then return null
158 # Special case for nit files
159 if git
.has_suffix
("/nit.git") then
165 private fun git_exec
(cmd
: String): nullable String do
166 var path
= package_path
167 if path
== null then return null
168 if not is_expanded
then path
= path
.dirname
169 with pr
= new ProcessReader("sh", "-c", "cd {path} && {cmd}") do
170 return pr
.read_all
.trim
174 private fun gen_ini
: String do
175 var ini_path
= self.ini_path
.as(not null)
176 var ini
= new ConfigTree(ini_path
)
178 ini
.update_value
("package.name", name
)
179 ini
.update_value
("package.desc", "")
180 ini
.update_value
("package.tags", "")
181 ini
.update_value
("package.maintainer", maintainer
)
182 ini
.update_value
("package.more_contributors", contributors
.join
(","))
183 ini
.update_value
("package.license", license
or else "")
185 ini
.update_value
("upstream.browse", browse_url
)
186 ini
.update_value
("upstream.git", git_url
)
187 ini
.update_value
("upstream.git.directory", git_dir
)
188 ini
.update_value
("upstream.homepage", homepage_url
)
189 ini
.update_value
("upstream.issues", issues_url
)
196 redef class ConfigTree
197 private fun update_value
(key
: String, value
: nullable String) do
198 if value
== null then return
199 if not has_key
(key
) then
202 var old_value
= self[key
]
203 if not value
.is_empty
and old_value
!= value
then
211 var toolcontext
= new ToolContext
212 var tpl
= new Template
213 tpl
.add
"Usage: nitpackage [OPTION]... <file.nit>...\n"
214 tpl
.add
"Helpful features about packages."
215 toolcontext
.tooldescription
= tpl
.write_to_string
218 toolcontext
.process_options
(args
)
219 var arguments
= toolcontext
.option_context
.rest
222 var model
= new Model
223 var mbuilder
= new ModelBuilder(model
, toolcontext
)
224 var mmodules
= mbuilder
.parse_full
(arguments
)
227 if mmodules
.is_empty
then return
229 toolcontext
.run_global_phases
(mmodules
)