exctl 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.attic/c_src/get-version.c +245 -0
- data/.document +5 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +72 -0
- data/LICENSE +20 -0
- data/OPERUM.md +17 -0
- data/README.md +17 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/lib/exctl.rb +0 -0
- data/notes.md +107 -0
- data/test/helper.rb +18 -0
- data/test/test_exctl.rb +7 -0
- metadata +128 -0
@@ -0,0 +1,245 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <unistd.h>
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <string.h>
|
5
|
+
#include <sys/param.h>
|
6
|
+
#include <sys/stat.h>
|
7
|
+
#include <sys/types.h>
|
8
|
+
#include <fcntl.h>
|
9
|
+
#include <time.h>
|
10
|
+
#include <sys/time.h>
|
11
|
+
#include <errno.h>
|
12
|
+
#define GCC_VERSION (__GNUC__ * 10000 \
|
13
|
+
+ __GNUC_MINOR__ * 100 \
|
14
|
+
+ __GNUC_PATCHLEVEL__)
|
15
|
+
#if GCC_VERSION >= 40500
|
16
|
+
#define _unreachable() __builtin_unreachable()
|
17
|
+
#else
|
18
|
+
#define _unreachable() do { abort(); } while(0)
|
19
|
+
#endif
|
20
|
+
#define xstr(N) #N
|
21
|
+
#define str(N) xstr(N)
|
22
|
+
#define perr() perror("ERROR [line " str(__LINE__) "]")
|
23
|
+
#define snap() {perr(); exit(1);}
|
24
|
+
#define $(EXPR) if((EXPR) == -1) snap()
|
25
|
+
#define $j(EXPR) if((EXPR) == -1) {perr(); goto err;}
|
26
|
+
|
27
|
+
size_t quick_run(char **argv, char *buf, size_t max_len) {
|
28
|
+
int pfildes[2];
|
29
|
+
$( pipe(pfildes) );
|
30
|
+
int pid = vfork();
|
31
|
+
if(!pid) {
|
32
|
+
close (pfildes[0]);
|
33
|
+
dup2 (pfildes[1],1);
|
34
|
+
close (pfildes[1]);
|
35
|
+
execvp(argv[0], argv);
|
36
|
+
perr();
|
37
|
+
_exit(1);
|
38
|
+
} else $( pid );
|
39
|
+
close(pfildes[1]);
|
40
|
+
ssize_t size = read(pfildes[0], buf, max_len - 1);
|
41
|
+
$( size );
|
42
|
+
buf[size] = '\0';
|
43
|
+
close(pfildes[0]);
|
44
|
+
return (size_t)size;
|
45
|
+
}
|
46
|
+
#if 0
|
47
|
+
// Safer version of quick_run if I ever run into trouble...
|
48
|
+
size_t quick_run(const char *cmd) {
|
49
|
+
FILE *proc = popen(cmd, "r");
|
50
|
+
size_t size = fread(proc_output, sizeof(proc_output)-1, sizeof(char), proc);
|
51
|
+
proc_output[size-1] = '\0';
|
52
|
+
pclose(proc);
|
53
|
+
return size;
|
54
|
+
}
|
55
|
+
#endif
|
56
|
+
|
57
|
+
|
58
|
+
void get_last_dirty_modification_stamp(char *buf, size_t max_size) {
|
59
|
+
int cwd;
|
60
|
+
cwd = 0;
|
61
|
+
char *cmd_gitroot [] = {"git", "rev-parse", "--show-toplevel", NULL};
|
62
|
+
char *cmd_gitdirty[] = {"git", "status", "--porcelain", "-uno", "-z", NULL};
|
63
|
+
int pfildes[2];
|
64
|
+
$j( pipe(pfildes) );
|
65
|
+
int pid = fork();
|
66
|
+
if(!pid) {
|
67
|
+
close (pfildes[0]);
|
68
|
+
dup2 (pfildes[1],1);
|
69
|
+
close (pfildes[1]);
|
70
|
+
execvp(cmd_gitdirty[0], cmd_gitdirty);
|
71
|
+
perr ( );
|
72
|
+
_exit (1);
|
73
|
+
_unreachable();
|
74
|
+
} else $j( pid );
|
75
|
+
close(pfildes[1]);
|
76
|
+
|
77
|
+
char pathbuf[MAXPATHLEN + 5];
|
78
|
+
$j(cwd = open(".", O_RDONLY));
|
79
|
+
size_t pathlen = quick_run(cmd_gitroot, pathbuf, sizeof(pathbuf));
|
80
|
+
pathbuf[pathlen - 1] = '\0'; // chomp
|
81
|
+
$j(chdir(pathbuf));
|
82
|
+
|
83
|
+
FILE *cmd_res = fdopen(pfildes[0], "r");
|
84
|
+
if(cmd_res == NULL) $j(-1);
|
85
|
+
|
86
|
+
char *line = pathbuf;
|
87
|
+
size_t linecap = MAXPATHLEN + 5;
|
88
|
+
ssize_t linelen;
|
89
|
+
int ignore_one = 0;
|
90
|
+
time_t newest_change = 0;
|
91
|
+
while( (linelen = getdelim(&line, &linecap, 0, cmd_res)) > 0) {
|
92
|
+
if(ignore_one) {
|
93
|
+
ignore_one = 0;
|
94
|
+
continue;
|
95
|
+
}
|
96
|
+
if(linelen > 3) {
|
97
|
+
if (line[1] == 'M' || line[0] == 'M' ||
|
98
|
+
line[1] == 'A' || line[0] == 'A' ||
|
99
|
+
line[1] == 'R' || line[0] == 'R' ||
|
100
|
+
line[1] == 'C' || line[0] == 'C' ||
|
101
|
+
line[1] == 'U' || line[0] == 'U' ||
|
102
|
+
line[1] == 'S' || line[0] == 'S' ||
|
103
|
+
line[1] == '?' || line[0] == '?') {
|
104
|
+
// git never uses 'S'- but without it there is no... Marcus?
|
105
|
+
ignore_one = (line[1] == 'R' || line[0] == 'R');
|
106
|
+
struct stat fst;
|
107
|
+
if(stat(&(line[3]), &fst) == -1) {
|
108
|
+
if(errno == ENOENT) continue;
|
109
|
+
$j(-1);
|
110
|
+
}
|
111
|
+
#ifdef __linux__
|
112
|
+
if(fst.st_mtime > newest_change) newest_change = fst.st_mtime;
|
113
|
+
#else
|
114
|
+
if(fst.st_mtimespec.tv_sec > newest_change) newest_change = fst.st_mtimespec.tv_sec;
|
115
|
+
#endif
|
116
|
+
}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
if(newest_change < 0) {
|
121
|
+
struct timeval tp;
|
122
|
+
gettimeofday(&tp, NULL);
|
123
|
+
newest_change = tp.tv_sec;
|
124
|
+
}
|
125
|
+
struct tm tmval;
|
126
|
+
gmtime_r(&(newest_change), &tmval);
|
127
|
+
strftime(buf, max_size-1, "d.%Y%m%d.%H%M%S",&tmval);
|
128
|
+
|
129
|
+
if(fchdir(cwd)){};
|
130
|
+
close(cwd);
|
131
|
+
fclose(cmd_res);
|
132
|
+
return;
|
133
|
+
|
134
|
+
err:
|
135
|
+
if(cwd) {
|
136
|
+
if(fchdir(cwd)){}
|
137
|
+
close(cwd);
|
138
|
+
}
|
139
|
+
exit(1);
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
#define adv(PCHR) while(*(PCHR) != '\0' && *(PCHR) != '-' && *(PCHR) != '\n'){(PCHR)++;} (PCHR)[0]='\0';(PCHR)++
|
144
|
+
#define pr(CONSTR) $(write(STDOUT_FILENO, CONSTR, sizeof(CONSTR)-1))
|
145
|
+
#define prs(BUF) $(write(STDOUT_FILENO, BUF, strnlen(BUF, 256)))
|
146
|
+
#define prl(BUF,LEN) $(write(STDOUT_FILENO, BUF, LEN))
|
147
|
+
|
148
|
+
int main(int argc, char **argv) {
|
149
|
+
int i;
|
150
|
+
int is_dirty;
|
151
|
+
|
152
|
+
// Commands
|
153
|
+
char *cmd_gitdesc[] = {"git","describe", "--match", "v[0-9.]*", "--dirty", "--long", "--always", NULL};
|
154
|
+
|
155
|
+
// Some constants and buffers
|
156
|
+
char describe_res [256] = {0};
|
157
|
+
char default_vmajor[] = "v0.0.0";
|
158
|
+
char default_vnumc [] = "0";
|
159
|
+
char unknown_vnumc [] = "u";
|
160
|
+
char dirty_is_true [32] = {0};
|
161
|
+
char dirty_is_false[] = "c";
|
162
|
+
|
163
|
+
// Destination strings for various pieces.
|
164
|
+
char *vhash = NULL;
|
165
|
+
char *vmajor = NULL;
|
166
|
+
char *vdirty = dirty_is_false;
|
167
|
+
char *vnum_commits = unknown_vnumc;
|
168
|
+
|
169
|
+
quick_run(cmd_gitdesc, describe_res, sizeof(describe_res) - 5); // -5 for padding for parser below
|
170
|
+
char *p = describe_res;
|
171
|
+
if(*p == 'v') {
|
172
|
+
vmajor = p++; // Got git tag w/ version
|
173
|
+
adv(p); // Advance past & terminate vmajor
|
174
|
+
// Next will be either num_commits or hash
|
175
|
+
char *pstart = p;
|
176
|
+
while(1) {
|
177
|
+
if(*p == '-') {
|
178
|
+
vnum_commits = pstart;
|
179
|
+
adv(p);
|
180
|
+
vhash = p++;
|
181
|
+
break;
|
182
|
+
} else if(*p < '0' || *p > '9') {
|
183
|
+
vhash = pstart;
|
184
|
+
vnum_commits = default_vnumc;
|
185
|
+
break;
|
186
|
+
}
|
187
|
+
p++;
|
188
|
+
}
|
189
|
+
} else {
|
190
|
+
vmajor = default_vmajor; // No git tag with a version
|
191
|
+
vhash = describe_res; // But we've got the vhash- skip to dirty-check
|
192
|
+
// TODO: calculate vnum_commits. In Ruby I was doing it like this:
|
193
|
+
// > plus_commits = `git shortlog -s`.scan(/\d+/) # should cut name off first
|
194
|
+
// > plus_commits = plus_commits.map{|p| p.to_i}.reduce(:+)
|
195
|
+
}
|
196
|
+
|
197
|
+
adv(p); // Advance to the end of and terminate the vhash
|
198
|
+
is_dirty = p[1] == 'i';
|
199
|
+
|
200
|
+
if(is_dirty) {
|
201
|
+
vdirty = dirty_is_true;
|
202
|
+
get_last_dirty_modification_stamp(vdirty, sizeof(dirty_is_true));
|
203
|
+
}
|
204
|
+
|
205
|
+
if(argc == 1) {
|
206
|
+
// Strictly the version
|
207
|
+
prs(vmajor);
|
208
|
+
if(is_dirty || vnum_commits[0]!='0') {
|
209
|
+
//pr ("+build.");
|
210
|
+
pr ("+");
|
211
|
+
prs(vnum_commits); pr (".");
|
212
|
+
prs(vdirty); pr (".");
|
213
|
+
if(vhash[0] != 'g') pr ("g");
|
214
|
+
prs(vhash);
|
215
|
+
}
|
216
|
+
pr("\n");
|
217
|
+
} else {
|
218
|
+
char *cmd_gitbranch[] = {"git", "rev-parse", "--abbrev-ref", "HEAD", NULL};
|
219
|
+
char gitbr[256];
|
220
|
+
size_t gitbr_size = quick_run(cmd_gitbranch, gitbr, sizeof(gitbr));
|
221
|
+
gitbr[gitbr_size - 1] = '\0'; // chomp
|
222
|
+
for(i=1; i<argc; i++) {
|
223
|
+
int j=0;
|
224
|
+
while(argv[i][j] != 0) {
|
225
|
+
if(argv[i][j] > 0x60 && argv[i][j] < 0x7B) argv[i][j] -= 0x20;
|
226
|
+
j++;
|
227
|
+
}
|
228
|
+
// Define statements
|
229
|
+
pr("#define "); prl(argv[i],j); pr("_VERSION_MAJOR_STR \""); prs(vmajor); pr("\"\n");
|
230
|
+
pr("#define "); prl(argv[i],j); pr("_VERSION_BUILD_STR \"");
|
231
|
+
if(is_dirty || vnum_commits[0]!='0') {
|
232
|
+
//pr("+build.");
|
233
|
+
pr("+"); prs(vnum_commits); pr("."); prs(vdirty); pr(".");
|
234
|
+
if(vhash[0] != 'g') pr("g"); prs(vhash);
|
235
|
+
}
|
236
|
+
pr("\"\n");
|
237
|
+
pr("#define "); prl(argv[i],j); pr("_VERSION_DETAILS_STR_BRANCH \""); prs(gitbr); pr("\"\n");
|
238
|
+
pr("#define "); prl(argv[i],j); pr("_VERSION_DETAILS_STR_COMMIT \"");
|
239
|
+
(vhash[0] == 'g') ? ({prs(&(vhash[1]))}) : ({prs(vhash)});
|
240
|
+
pr("\"\n");
|
241
|
+
}
|
242
|
+
}
|
243
|
+
|
244
|
+
return 0;
|
245
|
+
}
|
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "shoulda", ">= 0"
|
10
|
+
gem "rdoc", "~> 3.12"
|
11
|
+
gem "bundler", "~> 1.0"
|
12
|
+
gem "jeweler", "~> 1.8.7"
|
13
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activesupport (4.0.1)
|
5
|
+
i18n (~> 0.6, >= 0.6.4)
|
6
|
+
minitest (~> 4.2)
|
7
|
+
multi_json (~> 1.3)
|
8
|
+
thread_safe (~> 0.1)
|
9
|
+
tzinfo (~> 0.3.37)
|
10
|
+
addressable (2.3.5)
|
11
|
+
atomic (1.1.14)
|
12
|
+
builder (3.2.2)
|
13
|
+
faraday (0.8.8)
|
14
|
+
multipart-post (~> 1.2.0)
|
15
|
+
git (1.2.6)
|
16
|
+
github_api (0.10.1)
|
17
|
+
addressable
|
18
|
+
faraday (~> 0.8.1)
|
19
|
+
hashie (>= 1.2)
|
20
|
+
multi_json (~> 1.4)
|
21
|
+
nokogiri (~> 1.5.2)
|
22
|
+
oauth2
|
23
|
+
hashie (2.0.5)
|
24
|
+
highline (1.6.20)
|
25
|
+
httpauth (0.2.0)
|
26
|
+
i18n (0.6.5)
|
27
|
+
jeweler (1.8.8)
|
28
|
+
builder
|
29
|
+
bundler (~> 1.0)
|
30
|
+
git (>= 1.2.5)
|
31
|
+
github_api (= 0.10.1)
|
32
|
+
highline (>= 1.6.15)
|
33
|
+
nokogiri (= 1.5.10)
|
34
|
+
rake
|
35
|
+
rdoc
|
36
|
+
json (1.8.1)
|
37
|
+
jwt (0.1.8)
|
38
|
+
multi_json (>= 1.5)
|
39
|
+
minitest (4.7.5)
|
40
|
+
multi_json (1.8.2)
|
41
|
+
multi_xml (0.5.5)
|
42
|
+
multipart-post (1.2.0)
|
43
|
+
nokogiri (1.5.10)
|
44
|
+
oauth2 (0.9.2)
|
45
|
+
faraday (~> 0.8)
|
46
|
+
httpauth (~> 0.2)
|
47
|
+
jwt (~> 0.1.4)
|
48
|
+
multi_json (~> 1.0)
|
49
|
+
multi_xml (~> 0.5)
|
50
|
+
rack (~> 1.2)
|
51
|
+
rack (1.5.2)
|
52
|
+
rake (10.1.0)
|
53
|
+
rdoc (3.12.2)
|
54
|
+
json (~> 1.4)
|
55
|
+
shoulda (3.5.0)
|
56
|
+
shoulda-context (~> 1.0, >= 1.0.1)
|
57
|
+
shoulda-matchers (>= 1.4.1, < 3.0)
|
58
|
+
shoulda-context (1.1.5)
|
59
|
+
shoulda-matchers (2.4.0)
|
60
|
+
activesupport (>= 3.0.0)
|
61
|
+
thread_safe (0.1.3)
|
62
|
+
atomic
|
63
|
+
tzinfo (0.3.38)
|
64
|
+
|
65
|
+
PLATFORMS
|
66
|
+
ruby
|
67
|
+
|
68
|
+
DEPENDENCIES
|
69
|
+
bundler (~> 1.0)
|
70
|
+
jeweler (~> 1.8.7)
|
71
|
+
rdoc (~> 3.12)
|
72
|
+
shoulda
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Joseph Wecker
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/OPERUM.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
- () for simplicity, just quickly gcc get-version if required when running
|
2
|
+
- () default tasks
|
3
|
+
- () (project)
|
4
|
+
- () version
|
5
|
+
- () version.bump {.major|.minor|.patch} # Defaults to patch
|
6
|
+
- ()
|
7
|
+
|
8
|
+
- () (iterate)
|
9
|
+
- () test
|
10
|
+
- ()
|
11
|
+
|
12
|
+
- () (deploy)
|
13
|
+
- () hotfix (... ?)
|
14
|
+
- () release
|
15
|
+
- () git tag with verion (or do that with bump instead and use '-...' build info until it's released?)
|
16
|
+
- () Also generates the reltools release etc.?
|
17
|
+
- ()
|
data/README.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
exctl
|
2
|
+
=====
|
3
|
+
|
4
|
+
Project-specific command dispatcher using DRY and convention-over-configuration principles as much as possible.
|
5
|
+
|
6
|
+
So for a given project you will be able to create a command heirarchy (think `git *` or `gem *`- now you can make
|
7
|
+
`my-project *`) with the ability to detect and document (for command-line help as well as manpages) new tasks etc.
|
8
|
+
|
9
|
+
This allows you to have development-related tasks, packaging/installing/deployment-related tasks, and of course
|
10
|
+
runtime tasks (such as running the application).
|
11
|
+
|
12
|
+
Why? Because I've reimplemented this so many times for specific projects that I'm finally abstracting it.
|
13
|
+
|
14
|
+
Copyright
|
15
|
+
---------
|
16
|
+
|
17
|
+
Copyright (c) 2013 Joseph Wecker. See LICENSE for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "exctl"
|
18
|
+
gem.homepage = "http://github.com/josephwecker/exctl"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Project-specific command-line task dispatcher generator.}
|
21
|
+
gem.description = %Q{Allows you to create a command-line dispatcher for a project to consolidate dev, release, and runtime workflows.}
|
22
|
+
gem.email = "joseph.wecker@gmail.com"
|
23
|
+
gem.authors = ["Joseph Wecker"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
task :default => :test
|
36
|
+
|
37
|
+
require 'rdoc/task'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "exctl #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/exctl.rb
ADDED
File without changes
|
data/notes.md
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
why?
|
4
|
+
----
|
5
|
+
|
6
|
+
because I've done this over and over again:
|
7
|
+
|
8
|
+
- rake wrapper I did for jtv-web project (probably prettiest)
|
9
|
+
- imb- earlier metacon-like, then current dispatcher (most complete)
|
10
|
+
- quick command wrapper I did for fxsig
|
11
|
+
- metacon- bash version and start of C version
|
12
|
+
- some Proj stuff in shorthand
|
13
|
+
- lots of custom vim stuff that started to be a lot more project-aware
|
14
|
+
- I believe I might have even done one for zerl back in the day...
|
15
|
+
- not by me: rake, make, git, rebar, rvm, reltools output ctl script, most init.d type scripts...
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
meta-exctl
|
20
|
+
---------
|
21
|
+
- initiate project
|
22
|
+
- set up initial directory structure
|
23
|
+
- eventually different depending on various templates (e.g., erlang-apps, ruby gem, etc.)
|
24
|
+
- local version of exctl files
|
25
|
+
- create shell wrapper that has project-specific invocation name etc.
|
26
|
+
- command for dumping information about the project - including known tasks etc.
|
27
|
+
|
28
|
+
|
29
|
+
aggregate features
|
30
|
+
------------------
|
31
|
+
|
32
|
+
- (convention over configuration)
|
33
|
+
- quickly add and document external commands, scripts, code...
|
34
|
+
- wrap around and delegate to rake, rebar, mix, custom code, and/or standalone scripts/shell-commands
|
35
|
+
- dev/build tools integrated with / blended into server name
|
36
|
+
- families of (high-level) commands (ala git)
|
37
|
+
- families of commands (hierarchies- deps.get, db:create, ...)
|
38
|
+
- execute sequential commands
|
39
|
+
- default command (possibly contextual)
|
40
|
+
- commands with automatically triggered precondition commands
|
41
|
+
- semantic- explains itself, including most common / necessary commands (possibly contextual- i.e., build commands if it hasn't been built yet, run commands if it has, etc.)
|
42
|
+
- automatic manpage generation from same definitions?
|
43
|
+
- bash/zsh completion (automatically refreshed as necessary)
|
44
|
+
- very fast
|
45
|
+
- colored output
|
46
|
+
- default help, man, version (semantic & w/ git) commands
|
47
|
+
- allows for older style commandline args- at least expected gnu standards like -h, --help, -v, --version, etc.
|
48
|
+
- correctly manipulates environment variables before delegating
|
49
|
+
- @<env> environment shorthand
|
50
|
+
- always show environment except for possibly --version etc...
|
51
|
+
- default values
|
52
|
+
- post-format entered values
|
53
|
+
- allow for a configuration / environment / commandline-option option hierarchy
|
54
|
+
- multiple instances / servers / daemons running simultaneously and potentially aware of each other
|
55
|
+
- for compiled languages- make sure each environment has an isolated build target directory (including rel nodes for erlang, etc.)
|
56
|
+
- usually a fallback build method that is going to be expected by a maintainer
|
57
|
+
|
58
|
+
- tasks done "in the background" as much as possible- e.g., simply try to run the program and it will realize it needs
|
59
|
+
to compile the dev version first.
|
60
|
+
|
61
|
+
(and some new features)
|
62
|
+
|
63
|
+
- default 'status' command (long and short [for ps1 integration or something]) possibly plugin-able - git-state, build-state, coverage-state, running-instances, ...
|
64
|
+
- automatic environment detection- e.g., via hostname, cwd, whoami, etc.
|
65
|
+
- certain commands only allowed in certain environments
|
66
|
+
- good synchronity between git version / tags and erlang (etc.) releases
|
67
|
+
|
68
|
+
|
69
|
+
task families
|
70
|
+
--------------
|
71
|
+
interact with the project (bump, package, conformance-test, ...)
|
72
|
+
interact with the system / environment (deploy, start, stat, stop, ...)
|
73
|
+
interact with an instance of the application (upgrade, attach, test, ... environment-sensitive)
|
74
|
+
|
75
|
+
(
|
76
|
+
- local control (run, stop, attach, upgrade, downgrade, etc.- up/downgrade prefered to reload/restart)
|
77
|
+
- local testing, profiling, benchmarking, analyzing
|
78
|
+
- releasing, including integration, deployment, packaging, and release management
|
79
|
+
- project management (dependencies and submodules, ...)
|
80
|
+
)
|
81
|
+
|
82
|
+
(older misc notes)
|
83
|
+
-------------------
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
- Ability to have some kind of mock historical files for downloading during most tests
|
88
|
+
- test, dev, and prod all running on same machine without interfering with each other
|
89
|
+
-
|
90
|
+
|
91
|
+
- app-ctl tasks:
|
92
|
+
- init.d compatible:
|
93
|
+
- start
|
94
|
+
- stop
|
95
|
+
- restart
|
96
|
+
- try-restart (only restart if already running)
|
97
|
+
- reload
|
98
|
+
- force-reload
|
99
|
+
- status information on currently running app - maybe list showing available versions as well
|
100
|
+
|
101
|
+
- node controller:
|
102
|
+
|
103
|
+
- custom:
|
104
|
+
- help
|
105
|
+
- queued
|
106
|
+
-
|
107
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'exctl'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
data/test/test_exctl.rb
ADDED
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: exctl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Joseph Wecker
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-11-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: shoulda
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rdoc
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '3.12'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '3.12'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bundler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: jeweler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.8.7
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.8.7
|
78
|
+
description: Allows you to create a command-line dispatcher for a project to consolidate
|
79
|
+
dev, release, and runtime workflows.
|
80
|
+
email: joseph.wecker@gmail.com
|
81
|
+
executables: []
|
82
|
+
extensions: []
|
83
|
+
extra_rdoc_files:
|
84
|
+
- LICENSE
|
85
|
+
- README.md
|
86
|
+
files:
|
87
|
+
- .attic/c_src/get-version.c
|
88
|
+
- .document
|
89
|
+
- Gemfile
|
90
|
+
- Gemfile.lock
|
91
|
+
- LICENSE
|
92
|
+
- OPERUM.md
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- VERSION
|
96
|
+
- lib/exctl.rb
|
97
|
+
- notes.md
|
98
|
+
- test/helper.rb
|
99
|
+
- test/test_exctl.rb
|
100
|
+
homepage: http://github.com/josephwecker/exctl
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ! '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
segments:
|
114
|
+
- 0
|
115
|
+
hash: -3627039586448779554
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ! '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 1.8.25
|
125
|
+
signing_key:
|
126
|
+
specification_version: 3
|
127
|
+
summary: Project-specific command-line task dispatcher generator.
|
128
|
+
test_files: []
|