| @@ -0,0 +1,205 | |||
|
|
1 | # SOLID и контейнеры | |
|
|
2 | ||
|
|
3 | Рассмотрим простой пример того, как может быть построено приложения и почему приходится прибегать к такому сложному и непонятному решению как контейнеры. | |
|
|
4 | ||
|
|
5 | Допустим у нас есть приложение, которое работает с комментариями к товару, и мы решили разделить логику и работу с источником данных, разнеся ее между контроллером и контекстом данных и тут возникает вопрос, как они должны взаимодействовать друг с другом. | |
|
|
6 | ||
|
|
7 | ```ts | |
|
|
8 | // BAD | |
|
|
9 | class CommentsController { | |
|
|
10 | ||
|
|
11 | _db : DataContext, | |
|
|
12 | ||
|
|
13 | constructor(connectionString: string) { | |
|
|
14 | // explicit dependency | |
|
|
15 | this._db = new PgSqlDataContext(connectionString); | |
|
|
16 | } | |
|
|
17 | ||
|
|
18 | //... | |
|
|
19 | } | |
|
|
20 | ||
|
|
21 | // GOOD | |
|
|
22 | class CommmentsController { | |
|
|
23 | ||
|
|
24 | _db : DataContext, | |
|
|
25 | ||
|
|
26 | constructor(dataContext: DataContext) { | |
|
|
27 | // a dependency is passed through the constructor | |
|
|
28 | this._db = dataContext; | |
|
|
29 | } | |
|
|
30 | ||
|
|
31 | //... | |
|
|
32 | } | |
|
|
33 | ||
|
|
34 | // the container will do all the work | |
|
|
35 | // the container knows which DataContext to create | |
|
|
36 | let commentsController = container.getService<CommmentsController>("commmentsController"); | |
|
|
37 | ||
|
|
38 | //... | |
|
|
39 | ||
|
|
40 | commmentsController.createComment({ text: "Hello, unfair world!" }); | |
|
|
41 | ||
|
|
42 | ``` | |
|
|
43 | ||
|
|
44 | Для ответа на вопрос, что такое хорошо и что такое - плохо существует *SOLID* - набор принципов ООП при разработки программного обеспечения | |
|
|
45 | ||
|
|
46 | - **S**ingle responsibility | |
|
|
47 | - **O**pen-closed | |
|
|
48 | - **L**iskov substitution | |
|
|
49 | - **I**nterface segregation | |
|
|
50 | - **D**ependency inversion | |
|
|
51 | ||
|
|
52 | Использование данных принципов позволяет писать код, которыей будет обладать | |
|
|
53 | ||
|
|
54 | - повоторной используемостью | |
|
|
55 | - тестируемостью | |
|
|
56 | - читаемостью | |
|
|
57 | - поддаваться доработкам | |
|
|
58 | ||
|
|
59 | *IoC* Контейнеры являются инструментом для построения ПО согласно принциам SOLID, как клей связывают друг с другом компоненты. | |
|
|
60 | ||
|
|
61 | Контейнеры предоставляют стандарный механизм для описания и конструирования объектов, т.е. это некоторый объект в котором сосредоточена информация о сруктуре приложения и именно он должен создавать объекты и устанавливать между ними связи. Контейнер похож на шаблоны *абстрактная фабрика (Abstract Factory)* и *строитель (Builder)*. | |
|
|
62 | ||
|
|
63 | Для построения графа объектов контейнеру требуется конфигурация, которая состоит из набора дескрипторов сервисов, а также зависимостями между ними. | |
|
|
64 | ||
|
|
65 | Сервисы регистрируются в контейнере, каждый сервис имеет свое имя, позволяющее получить его у контейнера. | |
|
|
66 | ||
|
|
67 | ```js | |
|
|
68 | ||
|
|
69 | await container.configure({ | |
|
|
70 | db: { | |
|
|
71 | $type : 'my/app/PgSqlDataContext', | |
|
|
72 | params: { | |
|
|
73 | host: 'localhost', | |
|
|
74 | port: 5432 | |
|
|
75 | } | |
|
|
76 | }, | |
|
|
77 | commmentsController: { | |
|
|
78 | $type: 'my/app/CommmentsController', | |
|
|
79 | params: {$dependency: 'db'} | |
|
|
80 | } | |
|
|
81 | }); | |
|
|
82 | ||
|
|
83 | ``` | |
|
|
84 | ||
|
|
85 | В приведенном примере в контейнере объявляются два сервиса, один для работы с базой, воторой - для работы с комментариями. Между сервисами устанавливается зависимость, при создании `commmentsController` ему в контроллер передается созданный экземпляр контекста данных. | |
|
|
86 | ||
|
|
87 | Приложению остается только получить нужный сервис у контейнера и воспользоваться последним. | |
|
|
88 | ||
|
|
89 | > **Правило:** объекты не должны знать про контейнер! | |
|
|
90 | ||
|
|
91 | Очень важно соблюдать данное правило, поскольку если внутри класса будет использоваться контейнер, то он может запрашивать любые сервисы в любое время, что сильно усложнит отслеживание зависимостей. Исключением могут быть только объекты отвечающие за жизненный цикл приложения, которые создают и конфигурируют контейнер и не участвуют в бизнес-логике. | |
|
|
92 | ||
|
|
93 | Конфигурация контейнера является асинхронной операцией, поскольку может привести к загрузке модулей, где находятся объявления типов. Полностью сконфигурированный контейнер позволяет получать сервисы уже синхронно, что упрощает работу с ним и не тратит дополнительные ресурсы на использование асинхронных операций. | |
|
|
94 | ||
|
|
95 | ## Конфигурация | |
|
|
96 | ||
|
|
97 | Контейнер представляет собой словарь дескрипторов содержащих информацию о сервисах, в роли сервисов можно зарегистрировать: | |
|
|
98 | ||
|
|
99 | - типы | |
|
|
100 | - фабричные методы | |
|
|
101 | - существующие объекты и простые занчения | |
|
|
102 | ||
|
|
103 | подробоное описание конфигурации контейнера [di-config.md](di-config.md) | |
|
|
104 | ||
|
|
105 | ## Вложенные контейнеры | |
|
|
106 | ||
|
|
107 | Контейнеры могут создаваться на основе уже существующих, так называемые дочерние контейнеры, они получают все сервисы описанные в родительском контейнере. | |
|
|
108 | ||
|
|
109 | При изменении конфигурации дочернего контейнера - родительский контейнер останется без изменений. Использование дочерних контейнеров позволяет оптимизировать конфигурирование и дальнейшую работу с сервисами. | |
|
|
110 | ||
|
|
111 | Примером такой оптимизации может служить веб-приложение, в котором загружается контейнер для всего приложения, а для каждого запроса создается свой дочерний контейнер, который донастраивается контроллером запроса. По окончанию выполнения запроса дочерний контейнр уничтожается, освобождая ресурсы. | |
|
|
112 | ||
|
|
113 | ## Активация сервисов | |
|
|
114 | ||
|
|
115 | Активация - процесс, когда контейнер в ответ на запрос выдает экземпляр сервиса. При обработке запроса на получение сервиса контейнер создает контекст активации, всю работу по получению экземпляра сервиса выполняет дескриптор, которому передается контекст активации. | |
|
|
116 | ||
|
|
117 | 1. создается контекст активации, | |
|
|
118 | 2. ищется запись декриптора сервиса в контейнере, | |
|
|
119 | 3. дескриптору передается контекст активации, | |
|
|
120 | 4. дескриптор возвращает экземпляр сервиса. | |
|
|
121 | ||
|
|
122 | В процессе создания экземпляра сервиса, дескриптор может использовать контекст активации для обращения к контейнеру, текущим сервисам, а также может использовать его для активации других дескрипторов. | |
|
|
123 | ||
|
|
124 | ### Типы активации сервисов | |
|
|
125 | ||
|
|
126 | Тип активации относится к сервисам, в качестве которых были зарегистрированы либо типы, либо фабричные методы. | |
|
|
127 | ||
|
|
128 | ```ts | |
|
|
129 | ||
|
|
130 | container.configure({ | |
|
|
131 | foo: { | |
|
|
132 | $type: 'my/ServiceClass', | |
|
|
133 | activation: 'container' | |
|
|
134 | }, | |
|
|
135 | bar: { | |
|
|
136 | $factory: () => { | |
|
|
137 | return new ServiceClass(); | |
|
|
138 | }, | |
|
|
139 | activation: 'context' | |
|
|
140 | } | |
|
|
141 | }); | |
|
|
142 | ||
|
|
143 | ``` | |
|
|
144 | ||
|
|
145 | #### call | |
|
|
146 | ||
|
|
147 | Тип активации по-умолчанию, создается каждый раз, когда сервис запрашивается. | |
|
|
148 | ||
|
|
149 | #### context | |
|
|
150 | ||
|
|
151 | Экземпляр будет создан только один раз в рамках текущего контекста активации, т.е. при разрешении зависимостей будет использоваться все время один и тотже экземплар. | |
|
|
152 | ||
|
|
153 | #### container | |
|
|
154 | ||
|
|
155 | Будет создан только один экземпляр для контейнера, где сервис зарегистрирован. Созданный экземпляр сервиса будет автоматически очищен при освобождении контейнера. | |
|
|
156 | ||
|
|
157 | ```ts | |
|
|
158 | container.cofigure({ | |
|
|
159 | db: { | |
|
|
160 | $type : 'my/app/PgSqlDataContext', | |
|
|
161 | activation: 'container', | |
|
|
162 | params: { | |
|
|
163 | host: 'localhost', | |
|
|
164 | port: 5432 | |
|
|
165 | } | |
|
|
166 | } | |
|
|
167 | }) | |
|
|
168 | ||
|
|
169 | let db = container.getService<DataContext>('db'); | |
|
|
170 | ||
|
|
171 | let db2 = childContainer.getService<DataContext>('db'); | |
|
|
172 | ||
|
|
173 | //db === db2 | |
|
|
174 | ||
|
|
175 | container.dispose(); // will dispose db | |
|
|
176 | ||
|
|
177 | ``` | |
|
|
178 | ||
|
|
179 | #### hierarchy | |
|
|
180 | ||
|
|
181 | Будет создан только один экземпляр для контейнера, который создал контекст активации. Созданный экземпляр червиса будет автоматически очищен при освобождении контейнера. | |
|
|
182 | ||
|
|
183 | Данный вариант похож на тип активации `container`, но позволяет описать сервисы в родительском контейнере, а управлять временем жизни экземпляров этих сервисов при помощи дочерних контейнеров. Такой подход позволяет оптимизировать конфигурацию контейнеров. | |
|
|
184 | ||
|
|
185 | ```ts | |
|
|
186 | container.cofigure({ | |
|
|
187 | db: { | |
|
|
188 | $type : 'my/app/PgSqlDataContext', | |
|
|
189 | activation: 'hierarchy', | |
|
|
190 | params: { | |
|
|
191 | host: 'localhost', | |
|
|
192 | port: 5432 | |
|
|
193 | } | |
|
|
194 | } | |
|
|
195 | }) | |
|
|
196 | ||
|
|
197 | let db = container.getService<DataContext>('db'); | |
|
|
198 | ||
|
|
199 | let db2 = childContainer.getService<DataContext>('db'); | |
|
|
200 | ||
|
|
201 | //db !== db2 | |
|
|
202 | ||
|
|
203 | childContainer.dispose(); // will dispose db2, db will be left intact | |
|
|
204 | ||
|
|
205 | ``` No newline at end of file | |
|
|
1 | NO CONTENT: new file 100644, binary diff hidden |
| @@ -0,0 +1,5 | |||
|
|
1 | distributionBase=GRADLE_USER_HOME | |
|
|
2 | distributionPath=wrapper/dists | |
|
|
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip | |
|
|
4 | zipStoreBase=GRADLE_USER_HOME | |
|
|
5 | zipStorePath=wrapper/dists | |
| @@ -0,0 +1,172 | |||
|
|
1 | #!/usr/bin/env sh | |
|
|
2 | ||
|
|
3 | ############################################################################## | |
|
|
4 | ## | |
|
|
5 | ## Gradle start up script for UN*X | |
|
|
6 | ## | |
|
|
7 | ############################################################################## | |
|
|
8 | ||
|
|
9 | # Attempt to set APP_HOME | |
|
|
10 | # Resolve links: $0 may be a link | |
|
|
11 | PRG="$0" | |
|
|
12 | # Need this for relative symlinks. | |
|
|
13 | while [ -h "$PRG" ] ; do | |
|
|
14 | ls=`ls -ld "$PRG"` | |
|
|
15 | link=`expr "$ls" : '.*-> \(.*\)$'` | |
|
|
16 | if expr "$link" : '/.*' > /dev/null; then | |
|
|
17 | PRG="$link" | |
|
|
18 | else | |
|
|
19 | PRG=`dirname "$PRG"`"/$link" | |
|
|
20 | fi | |
|
|
21 | done | |
|
|
22 | SAVED="`pwd`" | |
|
|
23 | cd "`dirname \"$PRG\"`/" >/dev/null | |
|
|
24 | APP_HOME="`pwd -P`" | |
|
|
25 | cd "$SAVED" >/dev/null | |
|
|
26 | ||
|
|
27 | APP_NAME="Gradle" | |
|
|
28 | APP_BASE_NAME=`basename "$0"` | |
|
|
29 | ||
|
|
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |
|
|
31 | DEFAULT_JVM_OPTS="" | |
|
|
32 | ||
|
|
33 | # Use the maximum available, or set MAX_FD != -1 to use that value. | |
|
|
34 | MAX_FD="maximum" | |
|
|
35 | ||
|
|
36 | warn () { | |
|
|
37 | echo "$*" | |
|
|
38 | } | |
|
|
39 | ||
|
|
40 | die () { | |
|
|
41 | echo | |
|
|
42 | echo "$*" | |
|
|
43 | echo | |
|
|
44 | exit 1 | |
|
|
45 | } | |
|
|
46 | ||
|
|
47 | # OS specific support (must be 'true' or 'false'). | |
|
|
48 | cygwin=false | |
|
|
49 | msys=false | |
|
|
50 | darwin=false | |
|
|
51 | nonstop=false | |
|
|
52 | case "`uname`" in | |
|
|
53 | CYGWIN* ) | |
|
|
54 | cygwin=true | |
|
|
55 | ;; | |
|
|
56 | Darwin* ) | |
|
|
57 | darwin=true | |
|
|
58 | ;; | |
|
|
59 | MINGW* ) | |
|
|
60 | msys=true | |
|
|
61 | ;; | |
|
|
62 | NONSTOP* ) | |
|
|
63 | nonstop=true | |
|
|
64 | ;; | |
|
|
65 | esac | |
|
|
66 | ||
|
|
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | |
|
|
68 | ||
|
|
69 | # Determine the Java command to use to start the JVM. | |
|
|
70 | if [ -n "$JAVA_HOME" ] ; then | |
|
|
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | |
|
|
72 | # IBM's JDK on AIX uses strange locations for the executables | |
|
|
73 | JAVACMD="$JAVA_HOME/jre/sh/java" | |
|
|
74 | else | |
|
|
75 | JAVACMD="$JAVA_HOME/bin/java" | |
|
|
76 | fi | |
|
|
77 | if [ ! -x "$JAVACMD" ] ; then | |
|
|
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | |
|
|
79 | ||
|
|
80 | Please set the JAVA_HOME variable in your environment to match the | |
|
|
81 | location of your Java installation." | |
|
|
82 | fi | |
|
|
83 | else | |
|
|
84 | JAVACMD="java" | |
|
|
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |
|
|
86 | ||
|
|
87 | Please set the JAVA_HOME variable in your environment to match the | |
|
|
88 | location of your Java installation." | |
|
|
89 | fi | |
|
|
90 | ||
|
|
91 | # Increase the maximum file descriptors if we can. | |
|
|
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then | |
|
|
93 | MAX_FD_LIMIT=`ulimit -H -n` | |
|
|
94 | if [ $? -eq 0 ] ; then | |
|
|
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then | |
|
|
96 | MAX_FD="$MAX_FD_LIMIT" | |
|
|
97 | fi | |
|
|
98 | ulimit -n $MAX_FD | |
|
|
99 | if [ $? -ne 0 ] ; then | |
|
|
100 | warn "Could not set maximum file descriptor limit: $MAX_FD" | |
|
|
101 | fi | |
|
|
102 | else | |
|
|
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" | |
|
|
104 | fi | |
|
|
105 | fi | |
|
|
106 | ||
|
|
107 | # For Darwin, add options to specify how the application appears in the dock | |
|
|
108 | if $darwin; then | |
|
|
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" | |
|
|
110 | fi | |
|
|
111 | ||
|
|
112 | # For Cygwin, switch paths to Windows format before running java | |
|
|
113 | if $cygwin ; then | |
|
|
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` | |
|
|
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` | |
|
|
116 | JAVACMD=`cygpath --unix "$JAVACMD"` | |
|
|
117 | ||
|
|
118 | # We build the pattern for arguments to be converted via cygpath | |
|
|
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` | |
|
|
120 | SEP="" | |
|
|
121 | for dir in $ROOTDIRSRAW ; do | |
|
|
122 | ROOTDIRS="$ROOTDIRS$SEP$dir" | |
|
|
123 | SEP="|" | |
|
|
124 | done | |
|
|
125 | OURCYGPATTERN="(^($ROOTDIRS))" | |
|
|
126 | # Add a user-defined pattern to the cygpath arguments | |
|
|
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then | |
|
|
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" | |
|
|
129 | fi | |
|
|
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh | |
|
|
131 | i=0 | |
|
|
132 | for arg in "$@" ; do | |
|
|
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` | |
|
|
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option | |
|
|
135 | ||
|
|
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition | |
|
|
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` | |
|
|
138 | else | |
|
|
139 | eval `echo args$i`="\"$arg\"" | |
|
|
140 | fi | |
|
|
141 | i=$((i+1)) | |
|
|
142 | done | |
|
|
143 | case $i in | |
|
|
144 | (0) set -- ;; | |
|
|
145 | (1) set -- "$args0" ;; | |
|
|
146 | (2) set -- "$args0" "$args1" ;; | |
|
|
147 | (3) set -- "$args0" "$args1" "$args2" ;; | |
|
|
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; | |
|
|
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; | |
|
|
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; | |
|
|
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; | |
|
|
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; | |
|
|
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; | |
|
|
154 | esac | |
|
|
155 | fi | |
|
|
156 | ||
|
|
157 | # Escape application args | |
|
|
158 | save () { | |
|
|
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done | |
|
|
160 | echo " " | |
|
|
161 | } | |
|
|
162 | APP_ARGS=$(save "$@") | |
|
|
163 | ||
|
|
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules | |
|
|
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" | |
|
|
166 | ||
|
|
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong | |
|
|
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then | |
|
|
169 | cd "$(dirname "$0")" | |
|
|
170 | fi | |
|
|
171 | ||
|
|
172 | exec "$JAVACMD" "$@" | |
| @@ -0,0 +1,84 | |||
|
|
1 | @if "%DEBUG%" == "" @echo off | |
|
|
2 | @rem ########################################################################## | |
|
|
3 | @rem | |
|
|
4 | @rem Gradle startup script for Windows | |
|
|
5 | @rem | |
|
|
6 | @rem ########################################################################## | |
|
|
7 | ||
|
|
8 | @rem Set local scope for the variables with windows NT shell | |
|
|
9 | if "%OS%"=="Windows_NT" setlocal | |
|
|
10 | ||
|
|
11 | set DIRNAME=%~dp0 | |
|
|
12 | if "%DIRNAME%" == "" set DIRNAME=. | |
|
|
13 | set APP_BASE_NAME=%~n0 | |
|
|
14 | set APP_HOME=%DIRNAME% | |
|
|
15 | ||
|
|
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |
|
|
17 | set DEFAULT_JVM_OPTS= | |
|
|
18 | ||
|
|
19 | @rem Find java.exe | |
|
|
20 | if defined JAVA_HOME goto findJavaFromJavaHome | |
|
|
21 | ||
|
|
22 | set JAVA_EXE=java.exe | |
|
|
23 | %JAVA_EXE% -version >NUL 2>&1 | |
|
|
24 | if "%ERRORLEVEL%" == "0" goto init | |
|
|
25 | ||
|
|
26 | echo. | |
|
|
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |
|
|
28 | echo. | |
|
|
29 | echo Please set the JAVA_HOME variable in your environment to match the | |
|
|
30 | echo location of your Java installation. | |
|
|
31 | ||
|
|
32 | goto fail | |
|
|
33 | ||
|
|
34 | :findJavaFromJavaHome | |
|
|
35 | set JAVA_HOME=%JAVA_HOME:"=% | |
|
|
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe | |
|
|
37 | ||
|
|
38 | if exist "%JAVA_EXE%" goto init | |
|
|
39 | ||
|
|
40 | echo. | |
|
|
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% | |
|
|
42 | echo. | |
|
|
43 | echo Please set the JAVA_HOME variable in your environment to match the | |
|
|
44 | echo location of your Java installation. | |
|
|
45 | ||
|
|
46 | goto fail | |
|
|
47 | ||
|
|
48 | :init | |
|
|
49 | @rem Get command-line arguments, handling Windows variants | |
|
|
50 | ||
|
|
51 | if not "%OS%" == "Windows_NT" goto win9xME_args | |
|
|
52 | ||
|
|
53 | :win9xME_args | |
|
|
54 | @rem Slurp the command line arguments. | |
|
|
55 | set CMD_LINE_ARGS= | |
|
|
56 | set _SKIP=2 | |
|
|
57 | ||
|
|
58 | :win9xME_args_slurp | |
|
|
59 | if "x%~1" == "x" goto execute | |
|
|
60 | ||
|
|
61 | set CMD_LINE_ARGS=%* | |
|
|
62 | ||
|
|
63 | :execute | |
|
|
64 | @rem Setup the command line | |
|
|
65 | ||
|
|
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | |
|
|
67 | ||
|
|
68 | @rem Execute Gradle | |
|
|
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% | |
|
|
70 | ||
|
|
71 | :end | |
|
|
72 | @rem End local scope for the variables with windows NT shell | |
|
|
73 | if "%ERRORLEVEL%"=="0" goto mainEnd | |
|
|
74 | ||
|
|
75 | :fail | |
|
|
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | |
|
|
77 | rem the _cmd.exe /c_ return code! | |
|
|
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 | |
|
|
79 | exit /b 1 | |
|
|
80 | ||
|
|
81 | :mainEnd | |
|
|
82 | if "%OS%"=="Windows_NT" endlocal | |
|
|
83 | ||
|
|
84 | :omega | |
| @@ -0,0 +1,15 | |||
|
|
1 | /* | |
|
|
2 | * This settings file was generated by the Gradle 'init' task. | |
|
|
3 | * | |
|
|
4 | * The settings file is used to specify which projects to include in your build. | |
|
|
5 | * In a single project build this file can be empty or even removed. | |
|
|
6 | * | |
|
|
7 | * Detailed information about configuring a multi-project build in Gradle can be found | |
|
|
8 | * in the user guide at https://docs.gradle.org/3.5/userguide/multi_project_builds.html | |
|
|
9 | */ | |
|
|
10 | ||
|
|
11 | // To declare projects as part of a multi-project build use the 'include' method | |
|
|
12 | ||
|
|
13 | //include 'sub-project-name' | |
|
|
14 | ||
|
|
15 | rootProject.name = 'implab-core' No newline at end of file | |
| @@ -1,3 +1,6 | |||
|
|
1 | if (release != 'rtm') { | |
|
|
2 | version += "-$release" | |
|
|
3 | } | |
|
|
1 | 4 | |
|
|
2 | 5 | println "version: $version" |
|
|
3 | 6 | |
|
|
1 | NO CONTENT: file was removed |
|
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now
