change 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ .DS_Store
2
+ *.gem
3
+ .bundle
4
+ bin/murmur3
5
+ ext/change/change
6
+ ext/change/*.o
7
+ Gemfile.lock
8
+ pkg
9
+ spec/tmp
10
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2010
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ Change
2
+ ======
3
+
4
+ What files changed since last time?
5
+
6
+ With dependency management and super fast hashing ([Murmur3](https://github.com/PeterScott/murmur3)).
7
+
8
+ [![Build Status](https://secure.travis-ci.org/winton/change.png)](http://travis-ci.org/winton/change)
9
+
10
+ Requirements
11
+ ------------
12
+
13
+ gem install change
14
+
15
+ Changed?
16
+ --------
17
+
18
+ @change = Change.new("/absolute/path")
19
+ @change.d?("relative/path")
20
+ @change.d # { :add => [], :mod => [], :rem => [] }
21
+ @change.d(true) # reload
22
+
23
+ `Change` uses a YAML file stored in the root directory called `.change.yml` to maintain state.
24
+
25
+ Calling `@change.d?` does the following:
26
+
27
+ * Check if there is an entry for path in `.change.yml`
28
+ * If yes, read file size and compare with entry
29
+ * If file size matches, compare Murmur hash
30
+ * If no, record file size and Murmur hash
31
+ * Look up path in dependency tree
32
+ * If found, also mark all dependency parent paths as changed
33
+
34
+ Dependencies
35
+ ------------
36
+
37
+ To group dependencies, `Change` uses the concept of a "session":
38
+
39
+ @change = Change.new("/absolute/path")
40
+ @change.s(:some_id) # start session with id
41
+ @change.r("relative/path") # record dependency
42
+ @change.s(nil) # stop session
43
+
44
+ If you use `@change.d?` within a session, it will return true if any dependencies have changed. `Change` recalls the dependencies from the last session to achieve this.
45
+
46
+ @change.s(:some_id)
47
+ @change.d?('relative/path')
48
+ # returns true if any dependencies have changed
49
+ # dependencies are recalled from LAST :some_id session
50
+
51
+ Recall files that were modified during the last execution of this session:
52
+
53
+ @change.s(:some_id)
54
+ @change.d_ # returns: { :add => [], :mod => [], :rem => [] }
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'spec/rake/spectask'
3
+
4
+ Spec::Rake::SpecTask.new(:spec) do |t|
5
+ t.spec_files = FileList['spec/**/*_spec.rb']
6
+ end
7
+
8
+ task :default do
9
+ Dir.chdir("ext/change") do
10
+ system("make && make install")
11
+ end
12
+ Rake::Task['spec'].execute
13
+ end
data/bin/change ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path("../../lib/change", __FILE__)
data/change.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ root = File.expand_path('../', __FILE__)
3
+ lib = "#{root}/lib"
4
+
5
+ $:.unshift lib unless $:.include?(lib)
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "change"
9
+ s.version = '0.1.0'
10
+ s.platform = Gem::Platform::RUBY
11
+ s.authors = [ 'Winton Welsh' ]
12
+ s.email = [ 'mail@wintoni.us' ]
13
+ s.homepage = "http://github.com/winton/change"
14
+ s.summary = %q{What files changed since last time?}
15
+ s.description = %q{What files changed since last time? With dependency management and super fast hashing (Murmur3).}
16
+
17
+ s.executables = `cd #{root} && git ls-files bin/*`.split("\n").collect { |f| File.basename(f) }
18
+ s.extensions = [ 'ext/change/extconf.rb' ]
19
+ s.files = `cd #{root} && git ls-files`.split("\n")
20
+ s.require_paths = %w(lib)
21
+ s.test_files = `cd #{root} && git ls-files -- {features,test,spec}/*`.split("\n")
22
+
23
+ s.add_development_dependency "rake"
24
+ s.add_development_dependency "rspec", "~> 1.0"
25
+ end
@@ -0,0 +1,42 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <stdint.h>
4
+ #include <string.h>
5
+ #include "murmur3.h"
6
+
7
+ int main(int argc, char **argv) {
8
+ uint32_t hash[4]; /* Output for the hash */
9
+ uint32_t seed = 42; /* Seed value for hash */
10
+
11
+ int x;
12
+
13
+ for (x = 1; x < argc; x++) {
14
+ FILE *fh = fopen(argv[x], "rb");
15
+
16
+ if (fh != NULL) {
17
+ fseek(fh, 0L, SEEK_END);
18
+ long s = ftell(fh);
19
+
20
+ char *buffer = malloc(s + 1);
21
+ buffer[s] = '\0';
22
+
23
+ rewind(fh);
24
+
25
+ if (s != 0) {
26
+ fread(buffer, s, 1, fh);
27
+ fclose(fh);
28
+ fh = NULL;
29
+ }
30
+
31
+ MurmurHash3_x86_32(buffer, strlen(buffer), seed, hash);
32
+ printf("%08u\n", hash[0]);
33
+
34
+ free(buffer);
35
+
36
+ if (fh != NULL)
37
+ fclose(fh);
38
+ }
39
+ }
40
+
41
+ return 0;
42
+ }
File without changes
@@ -0,0 +1,8 @@
1
+ CFLAGS = -O2 -Wall
2
+
3
+ all: change
4
+ change: change.o murmur3.o
5
+ install:
6
+ rm *.o
7
+ mv -f change ../../bin/murmur3
8
+ chmod +x ../../bin/murmur3
@@ -0,0 +1,315 @@
1
+ //-----------------------------------------------------------------------------
2
+ // MurmurHash3 was written by Austin Appleby, and is placed in the public
3
+ // domain. The author hereby disclaims copyright to this source code.
4
+
5
+ // Note - The x86 and x64 versions do _not_ produce the same results, as the
6
+ // algorithms are optimized for their respective platforms. You can still
7
+ // compile and run any of them on any platform, but your performance with the
8
+ // non-native version will be less than optimal.
9
+
10
+ #include "murmur3.h"
11
+
12
+ //-----------------------------------------------------------------------------
13
+ // Platform-specific functions and macros
14
+
15
+ #ifdef __GNUC__
16
+ #define FORCE_INLINE __attribute__((always_inline))
17
+ #else
18
+ #define FORCE_INLINE
19
+ #endif
20
+
21
+ static inline FORCE_INLINE uint32_t rotl32 ( uint32_t x, int8_t r )
22
+ {
23
+ return (x << r) | (x >> (32 - r));
24
+ }
25
+
26
+ static inline FORCE_INLINE uint64_t rotl64 ( uint64_t x, int8_t r )
27
+ {
28
+ return (x << r) | (x >> (64 - r));
29
+ }
30
+
31
+ #define ROTL32(x,y) rotl32(x,y)
32
+ #define ROTL64(x,y) rotl64(x,y)
33
+
34
+ #define BIG_CONSTANT(x) (x##LLU)
35
+
36
+ //-----------------------------------------------------------------------------
37
+ // Block read - if your platform needs to do endian-swapping or can only
38
+ // handle aligned reads, do the conversion here
39
+
40
+ #define getblock(p, i) (p[i])
41
+
42
+ //-----------------------------------------------------------------------------
43
+ // Finalization mix - force all bits of a hash block to avalanche
44
+
45
+ static inline FORCE_INLINE uint32_t fmix32 ( uint32_t h )
46
+ {
47
+ h ^= h >> 16;
48
+ h *= 0x85ebca6b;
49
+ h ^= h >> 13;
50
+ h *= 0xc2b2ae35;
51
+ h ^= h >> 16;
52
+
53
+ return h;
54
+ }
55
+
56
+ //----------
57
+
58
+ static inline FORCE_INLINE uint64_t fmix64 ( uint64_t k )
59
+ {
60
+ k ^= k >> 33;
61
+ k *= BIG_CONSTANT(0xff51afd7ed558ccd);
62
+ k ^= k >> 33;
63
+ k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
64
+ k ^= k >> 33;
65
+
66
+ return k;
67
+ }
68
+
69
+ //-----------------------------------------------------------------------------
70
+
71
+ void MurmurHash3_x86_32 ( const void * key, int len,
72
+ uint32_t seed, void * out )
73
+ {
74
+ const uint8_t * data = (const uint8_t*)key;
75
+ const int nblocks = len / 4;
76
+ int i;
77
+
78
+ uint32_t h1 = seed;
79
+
80
+ uint32_t c1 = 0xcc9e2d51;
81
+ uint32_t c2 = 0x1b873593;
82
+
83
+ //----------
84
+ // body
85
+
86
+ const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
87
+
88
+ for(i = -nblocks; i; i++)
89
+ {
90
+ uint32_t k1 = getblock(blocks,i);
91
+
92
+ k1 *= c1;
93
+ k1 = ROTL32(k1,15);
94
+ k1 *= c2;
95
+
96
+ h1 ^= k1;
97
+ h1 = ROTL32(h1,13);
98
+ h1 = h1*5+0xe6546b64;
99
+ }
100
+
101
+ //----------
102
+ // tail
103
+
104
+ const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
105
+
106
+ uint32_t k1 = 0;
107
+
108
+ switch(len & 3)
109
+ {
110
+ case 3: k1 ^= tail[2] << 16;
111
+ case 2: k1 ^= tail[1] << 8;
112
+ case 1: k1 ^= tail[0];
113
+ k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
114
+ };
115
+
116
+ //----------
117
+ // finalization
118
+
119
+ h1 ^= len;
120
+
121
+ h1 = fmix32(h1);
122
+
123
+ *(uint32_t*)out = h1;
124
+ }
125
+
126
+ //-----------------------------------------------------------------------------
127
+
128
+ void MurmurHash3_x86_128 ( const void * key, const int len,
129
+ uint32_t seed, void * out )
130
+ {
131
+ const uint8_t * data = (const uint8_t*)key;
132
+ const int nblocks = len / 16;
133
+ int i;
134
+
135
+ uint32_t h1 = seed;
136
+ uint32_t h2 = seed;
137
+ uint32_t h3 = seed;
138
+ uint32_t h4 = seed;
139
+
140
+ uint32_t c1 = 0x239b961b;
141
+ uint32_t c2 = 0xab0e9789;
142
+ uint32_t c3 = 0x38b34ae5;
143
+ uint32_t c4 = 0xa1e38b93;
144
+
145
+ //----------
146
+ // body
147
+
148
+ const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
149
+
150
+ for(i = -nblocks; i; i++)
151
+ {
152
+ uint32_t k1 = getblock(blocks,i*4+0);
153
+ uint32_t k2 = getblock(blocks,i*4+1);
154
+ uint32_t k3 = getblock(blocks,i*4+2);
155
+ uint32_t k4 = getblock(blocks,i*4+3);
156
+
157
+ k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
158
+
159
+ h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
160
+
161
+ k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
162
+
163
+ h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
164
+
165
+ k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
166
+
167
+ h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
168
+
169
+ k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
170
+
171
+ h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
172
+ }
173
+
174
+ //----------
175
+ // tail
176
+
177
+ const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
178
+
179
+ uint32_t k1 = 0;
180
+ uint32_t k2 = 0;
181
+ uint32_t k3 = 0;
182
+ uint32_t k4 = 0;
183
+
184
+ switch(len & 15)
185
+ {
186
+ case 15: k4 ^= tail[14] << 16;
187
+ case 14: k4 ^= tail[13] << 8;
188
+ case 13: k4 ^= tail[12] << 0;
189
+ k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
190
+
191
+ case 12: k3 ^= tail[11] << 24;
192
+ case 11: k3 ^= tail[10] << 16;
193
+ case 10: k3 ^= tail[ 9] << 8;
194
+ case 9: k3 ^= tail[ 8] << 0;
195
+ k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
196
+
197
+ case 8: k2 ^= tail[ 7] << 24;
198
+ case 7: k2 ^= tail[ 6] << 16;
199
+ case 6: k2 ^= tail[ 5] << 8;
200
+ case 5: k2 ^= tail[ 4] << 0;
201
+ k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
202
+
203
+ case 4: k1 ^= tail[ 3] << 24;
204
+ case 3: k1 ^= tail[ 2] << 16;
205
+ case 2: k1 ^= tail[ 1] << 8;
206
+ case 1: k1 ^= tail[ 0] << 0;
207
+ k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
208
+ };
209
+
210
+ //----------
211
+ // finalization
212
+
213
+ h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
214
+
215
+ h1 += h2; h1 += h3; h1 += h4;
216
+ h2 += h1; h3 += h1; h4 += h1;
217
+
218
+ h1 = fmix32(h1);
219
+ h2 = fmix32(h2);
220
+ h3 = fmix32(h3);
221
+ h4 = fmix32(h4);
222
+
223
+ h1 += h2; h1 += h3; h1 += h4;
224
+ h2 += h1; h3 += h1; h4 += h1;
225
+
226
+ ((uint32_t*)out)[0] = h1;
227
+ ((uint32_t*)out)[1] = h2;
228
+ ((uint32_t*)out)[2] = h3;
229
+ ((uint32_t*)out)[3] = h4;
230
+ }
231
+
232
+ //-----------------------------------------------------------------------------
233
+
234
+ void MurmurHash3_x64_128 ( const void * key, const int len,
235
+ const uint32_t seed, void * out )
236
+ {
237
+ const uint8_t * data = (const uint8_t*)key;
238
+ const int nblocks = len / 16;
239
+ int i;
240
+
241
+ uint64_t h1 = seed;
242
+ uint64_t h2 = seed;
243
+
244
+ uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
245
+ uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
246
+
247
+ //----------
248
+ // body
249
+
250
+ const uint64_t * blocks = (const uint64_t *)(data);
251
+
252
+ for(i = 0; i < nblocks; i++)
253
+ {
254
+ uint64_t k1 = getblock(blocks,i*2+0);
255
+ uint64_t k2 = getblock(blocks,i*2+1);
256
+
257
+ k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
258
+
259
+ h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
260
+
261
+ k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
262
+
263
+ h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
264
+ }
265
+
266
+ //----------
267
+ // tail
268
+
269
+ const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
270
+
271
+ uint64_t k1 = 0;
272
+ uint64_t k2 = 0;
273
+
274
+ switch(len & 15)
275
+ {
276
+ case 15: k2 ^= (uint64_t)(tail[14]) << 48;
277
+ case 14: k2 ^= (uint64_t)(tail[13]) << 40;
278
+ case 13: k2 ^= (uint64_t)(tail[12]) << 32;
279
+ case 12: k2 ^= (uint64_t)(tail[11]) << 24;
280
+ case 11: k2 ^= (uint64_t)(tail[10]) << 16;
281
+ case 10: k2 ^= (uint64_t)(tail[ 9]) << 8;
282
+ case 9: k2 ^= (uint64_t)(tail[ 8]) << 0;
283
+ k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
284
+
285
+ case 8: k1 ^= (uint64_t)(tail[ 7]) << 56;
286
+ case 7: k1 ^= (uint64_t)(tail[ 6]) << 48;
287
+ case 6: k1 ^= (uint64_t)(tail[ 5]) << 40;
288
+ case 5: k1 ^= (uint64_t)(tail[ 4]) << 32;
289
+ case 4: k1 ^= (uint64_t)(tail[ 3]) << 24;
290
+ case 3: k1 ^= (uint64_t)(tail[ 2]) << 16;
291
+ case 2: k1 ^= (uint64_t)(tail[ 1]) << 8;
292
+ case 1: k1 ^= (uint64_t)(tail[ 0]) << 0;
293
+ k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
294
+ };
295
+
296
+ //----------
297
+ // finalization
298
+
299
+ h1 ^= len; h2 ^= len;
300
+
301
+ h1 += h2;
302
+ h2 += h1;
303
+
304
+ h1 = fmix64(h1);
305
+ h2 = fmix64(h2);
306
+
307
+ h1 += h2;
308
+ h2 += h1;
309
+
310
+ ((uint64_t*)out)[0] = h1;
311
+ ((uint64_t*)out)[1] = h2;
312
+ }
313
+
314
+ //-----------------------------------------------------------------------------
315
+
@@ -0,0 +1,21 @@
1
+ //-----------------------------------------------------------------------------
2
+ // MurmurHash3 was written by Austin Appleby, and is placed in the
3
+ // public domain. The author hereby disclaims copyright to this source
4
+ // code.
5
+
6
+ #ifndef _MURMURHASH3_H_
7
+ #define _MURMURHASH3_H_
8
+
9
+ #include <stdint.h>
10
+
11
+ //-----------------------------------------------------------------------------
12
+
13
+ void MurmurHash3_x86_32 (const void *key, int len, uint32_t seed, void *out);
14
+
15
+ void MurmurHash3_x86_128(const void *key, int len, uint32_t seed, void *out);
16
+
17
+ void MurmurHash3_x64_128(const void *key, int len, uint32_t seed, void *out);
18
+
19
+ //-----------------------------------------------------------------------------
20
+
21
+ #endif // _MURMURHASH3_H_
data/lib/change.rb ADDED
@@ -0,0 +1,114 @@
1
+ require 'yaml'
2
+
3
+ $:.unshift File.dirname(__FILE__)
4
+
5
+ class Change
6
+
7
+ def initialize(root)
8
+ @root = File.expand_path(root)
9
+ end
10
+
11
+ def d?(path)
12
+ changed = @d.values.flatten
13
+ if @session && @last_deps && @last_deps.include?(path)
14
+ @last_deps.any? { |p| changed.include?(p) }
15
+ else
16
+ changed.include?(path)
17
+ end
18
+ end
19
+
20
+ def d(reload=false)
21
+ if @d && !reload
22
+ @d
23
+ else
24
+ paths = Dir.chdir(@root) { Dir["**/*"] }
25
+ add = paths - states.keys
26
+ rem = states.keys - paths
27
+ hashes = murmur_hashes(paths)
28
+
29
+ mod = paths.inject([]) do |array, path|
30
+ hash = hashes[path]
31
+ size = Dir.chdir(@root) { File.size(path) }
32
+
33
+ if states[path] && size != states[path][:size]
34
+ array << path
35
+ elsif states[path] && hash != states[path][:hash]
36
+ array << path
37
+ end
38
+
39
+ states[path] ||= {}
40
+ states[path][:hash] = hash
41
+ states[path][:size] = size
42
+
43
+ array
44
+ end
45
+
46
+ mod -= add
47
+ rem.each { |path| states.delete(path) }
48
+
49
+ write!
50
+
51
+ @d = { :add => add, :mod => mod, :rem => rem }
52
+ end
53
+ end
54
+
55
+ def d_
56
+ @last_session
57
+ end
58
+
59
+ def r(path)
60
+ if @session
61
+ deps[@session].push(path)
62
+ deps[@session].uniq!
63
+ write!
64
+ end
65
+ end
66
+
67
+ def s(id)
68
+ d(true)
69
+
70
+ if @session && @session != id
71
+ @last_session = sessions[@session] = d
72
+ write!
73
+ end
74
+
75
+ @session = id
76
+ @last_deps = @session ? deps[@session] : nil
77
+ deps[@session] = [] if @session
78
+ end
79
+
80
+ private
81
+
82
+ def data
83
+ @data ||= (YAML.load(File.read("#{@root}/.change.yml")) rescue {})
84
+ end
85
+
86
+ def murmur_bin
87
+ @murmur ||= File.expand_path('../../bin/murmur3', __FILE__)
88
+ end
89
+
90
+ def murmur_hashes(paths)
91
+ hashes = Dir.chdir(@root) do
92
+ `#{murmur_bin} #{paths.collect { |m| "'#{m}'" }.join(' ')}`
93
+ end
94
+ Hash[paths.zip(hashes.split("\n"))]
95
+ end
96
+
97
+ def deps
98
+ data['deps'] ||= {}
99
+ end
100
+
101
+ def sessions
102
+ data['sessions'] ||= {}
103
+ end
104
+
105
+ def states
106
+ data['states'] ||= {}
107
+ end
108
+
109
+ def write!
110
+ File.open("#{@root}/.change.yml", 'w') do |f|
111
+ f.write(YAML.dump(data))
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,115 @@
1
+ require 'fileutils'
2
+ require 'spec_helper'
3
+
4
+ describe ::Change do
5
+
6
+ before :all do
7
+ @root = File.expand_path('../../', __FILE__)
8
+ FileUtils.rm_rf(@tmp = "#{@root}/spec/tmp")
9
+ FileUtils.cp_r("#{@root}/spec/fixture", @tmp)
10
+ @change = ::Change.new(@tmp)
11
+ end
12
+
13
+ describe :d do
14
+ it "should return all files as added" do
15
+ @change.d.should == {
16
+ :add => [ "modify.txt", "remove.txt" ],
17
+ :mod => [],
18
+ :rem => []
19
+ }
20
+ end
21
+
22
+ it "should cache last changes" do
23
+ @change.d.should == {
24
+ :add => [ "modify.txt", "remove.txt" ],
25
+ :mod => [],
26
+ :rem => []
27
+ }
28
+ end
29
+
30
+ it "should return no files modified" do
31
+ @change.d(true).should == {
32
+ :add => [],
33
+ :mod => [],
34
+ :rem => []
35
+ }
36
+ end
37
+
38
+ it "should return modified" do
39
+ File.open("#{@tmp}/modify.txt", 'w') { |f| f.write('!') }
40
+ @change.d(true).should == {
41
+ :add => [],
42
+ :mod => [ "modify.txt" ],
43
+ :rem => []
44
+ }
45
+ end
46
+
47
+ it "should return removed" do
48
+ FileUtils.rm("#{@tmp}/remove.txt")
49
+ @change.d(true).should == {
50
+ :add => [],
51
+ :mod => [],
52
+ :rem => [ "remove.txt" ]
53
+ }
54
+ end
55
+
56
+ it "should return added" do
57
+ File.open("#{@tmp}/add.txt", 'w') { |f| f.write('!') }
58
+ @change.d(true).should == {
59
+ :add => [ "add.txt" ],
60
+ :mod => [],
61
+ :rem => []
62
+ }
63
+ end
64
+
65
+ it "should save state" do
66
+ @change = ::Change.new(@tmp)
67
+ @change.d.should == {
68
+ :add => [],
69
+ :mod => [],
70
+ :rem => []
71
+ }
72
+ end
73
+ end
74
+
75
+ describe :d? do
76
+ it "should return changed boolean" do
77
+ File.open("#{@tmp}/modify.txt", 'w') { |f| f.write('!!') }
78
+ @change.d(true)
79
+ @change.d?('add.txt').should == false
80
+ @change.d?('modify.txt').should == true
81
+ end
82
+ end
83
+
84
+ describe :s do
85
+ before :all do
86
+ @change.s(:id)
87
+ @change.r('modify.txt')
88
+ @change.r('remove.txt')
89
+ File.open("#{@tmp}/add.txt", 'w') { |f| f.write('!') }
90
+ File.open("#{@tmp}/modify.txt", 'w') { |f| f.write('!!!') }
91
+ @change.s(nil)
92
+ end
93
+
94
+ it "should record dependencies" do
95
+ @change.send(:deps).should == { :id => [ "modify.txt", "remove.txt" ] }
96
+ end
97
+
98
+ it "should record files modified during session" do
99
+ @change.send(:sessions).should == {
100
+ :id => {
101
+ :add => [ "add.txt" ], :mod => [ "modify.txt" ], :rem => []
102
+ }
103
+ }
104
+ end
105
+
106
+ it "should return proper data within next session" do
107
+ File.open("#{@tmp}/modify.txt", 'w') { |f| f.write('!!!!') }
108
+ @change.s(:id)
109
+ @change.d?("remove.txt").should == true
110
+ @change.d.should == { :add => [], :mod => [ "modify.txt" ], :rem => [] }
111
+ @change.d_.should == { :add => [ "add.txt" ], :mod => [ "modify.txt" ], :rem => [] }
112
+ @change.s(nil)
113
+ end
114
+ end
115
+ end
File without changes
File without changes
@@ -0,0 +1,8 @@
1
+ require "pp"
2
+ require "bundler"
3
+
4
+ Bundler.require(:development)
5
+
6
+ $root = File.expand_path('../../', __FILE__)
7
+
8
+ require "#{$root}/lib/change"
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: change
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Winton Welsh
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-07-07 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rake
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rspec
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ hash: 15
43
+ segments:
44
+ - 1
45
+ - 0
46
+ version: "1.0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ description: What files changed since last time? With dependency management and super fast hashing (Murmur3).
50
+ email:
51
+ - mail@wintoni.us
52
+ executables:
53
+ - change
54
+ extensions:
55
+ - ext/change/extconf.rb
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - .gitignore
60
+ - .travis.yml
61
+ - Gemfile
62
+ - LICENSE
63
+ - README.md
64
+ - Rakefile
65
+ - bin/change
66
+ - change.gemspec
67
+ - ext/change/change.c
68
+ - ext/change/extconf.rb
69
+ - ext/change/makefile
70
+ - ext/change/murmur3.c
71
+ - ext/change/murmur3.h
72
+ - lib/change.rb
73
+ - spec/change_spec.rb
74
+ - spec/fixture/modify.txt
75
+ - spec/fixture/remove.txt
76
+ - spec/spec_helper.rb
77
+ homepage: http://github.com/winton/change
78
+ licenses: []
79
+
80
+ post_install_message:
81
+ rdoc_options: []
82
+
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ requirements: []
104
+
105
+ rubyforge_project:
106
+ rubygems_version: 1.8.24
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: What files changed since last time?
110
+ test_files:
111
+ - spec/change_spec.rb
112
+ - spec/fixture/modify.txt
113
+ - spec/fixture/remove.txt
114
+ - spec/spec_helper.rb