nitc: extract common app.nit annotations from Android
[nit.git] / src / platform / app_annotations.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
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
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 # Annotations to gather metadata on `app.nit` projects
16 module app_annotations
17
18 private import parser_util
19 import modelize
20 import literal
21 import semantize
22 private import annotation
23
24 # Metadata associated to an Android project
25 class AppProject
26 # Name of the resulting application
27 var name: nullable String = null
28
29 # Namespace/package used to identify the application
30 var namespace: nullable String = null
31
32 # Version of the application
33 var version: nullable String = null
34
35 # Numerical version code of the application
36 var version_code: Int = 0
37
38 private var modelbuilder: ModelBuilder
39 private var mainmodule: MModule
40
41 init
42 do
43 var annot = modelbuilder.lookup_annotation_on_modules("app_name", mainmodule)
44 if annot != null then name = annot.arg_as_string(modelbuilder)
45
46 annot = modelbuilder.lookup_annotation_on_modules("app_version", mainmodule)
47 if annot != null then version = annot.as_version(modelbuilder)
48
49 annot = modelbuilder.lookup_annotation_on_modules("app_namespace", mainmodule)
50 if annot != null then namespace = annot.arg_as_string(modelbuilder)
51
52 # Get the date and time (down to the minute) as string
53 var local_time = new Tm.localtime
54 var local_time_s = local_time.strftime("%y%m%d%H%M")
55 version_code = local_time_s.to_i
56
57 modelbuilder.toolcontext.check_errors
58 end
59
60 redef fun to_s do return """
61 name: {{{name or else "null"}}}
62 namespace: {{{namespace or else "null"}}}
63 version: {{{version or else "null"}}}"""
64 end
65
66 redef class AAnnotation
67 # Returns a version string (example: "1.5.6b42a7c") from an annotation `version(1, 5, git_revision)`.
68 #
69 # The user can enter as many fields as needed. The call to `git_revision` will be replaced by the short
70 # revision number. If the working tree is dirty, it will append another field with "d" for dirty.
71 private fun as_version(modelbuilder: ModelBuilder): String
72 do
73 var version_fields = new Array[Object]
74
75 var args = n_args
76 if args.length < 1 then
77 modelbuilder.error(self, "Annotation error: \"{name}\" expects at least a single argument.")
78 return ""
79 else
80 for arg in args do
81 var format_error = "Annotation error: \"{name}\" expects its arguments to be of type Int or a call to `git_revision`"
82
83 var value
84 value = arg.as_int
85 if value != null then
86 version_fields.add value
87 continue
88 end
89
90 value = arg.as_string
91 if value != null then
92 version_fields.add value
93 end
94
95 value = arg.as_id
96 if value == "git_revision" then
97 # Get Git short revision
98 var proc = new ProcessReader("git", "rev-parse", "--short", "HEAD")
99 proc.wait
100 assert proc.status == 0
101 var lines = proc.read_all
102 var revision = lines.split("\n").first
103
104 # Is it dirty?
105 # If not, the return of `git diff --shortstat` is an empty line
106 proc = new ProcessReader("git", "diff-index", "--quiet", "HEAD")
107 proc.wait
108 var dirty = proc.status != 0
109 if dirty then revision += ".d"
110
111 version_fields.add revision
112 continue
113 end
114
115 modelbuilder.error(self, format_error)
116 return ""
117 end
118 end
119
120 return version_fields.join(".")
121 end
122 end