change 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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