mtime_cache 1.0.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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/bin/mtime_cache +175 -0
  3. metadata +56 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fb9b0b0398347bc369ed59a49ace2c54ee2392d4
4
+ data.tar.gz: 2664bb3feae73052c30f95c18f17dde52843ac82
5
+ SHA512:
6
+ metadata.gz: 776fd395224e7457e1878f0795e3ff48e980a6476ee5d234a93c390136f04e4782722cdd5eb287679576d55b30f3766ee23a9701ca7b8717129f088141beee28
7
+ data.tar.gz: e9d377e6f250081fbbd8d78a19f84b58e780d2d7dac09bb4d033be4744b5b8c0294447edeff1813a05e15a102b9286c482610986c6e2fcad0cfdb7bb722b4f52
data/bin/mtime_cache ADDED
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # mtime_cache
5
+ # Copyright (c) 2016 Borislav Stanimirov
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to
9
+ # deal in the Software without restriction, including without limitation the
10
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11
+ # sell copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
+ # IN THE SOFTWARE.
24
+ #
25
+
26
+ require 'digest/md5'
27
+ require 'json'
28
+ require 'fileutils'
29
+
30
+ VERSION = "1.0.0"
31
+
32
+ VERSION_TEXT = "mtime_cache v#{VERSION}"
33
+
34
+ USAGE = <<ENDUSAGE
35
+
36
+ Usage:
37
+ mtime_cache [<globs>] [-g globfile] [-d] [-q|V] [-c cache]
38
+ ENDUSAGE
39
+
40
+ HELP = <<ENDHELP
41
+
42
+ Traverse through globbed files, making a json cache based on their mtime.
43
+ If a cache exists, changes the mtime of existing unchanged (based on MD5
44
+ hash) files to the one in the cache.
45
+
46
+ Options:
47
+
48
+ globs Ruby-compatible glob strings (ex some/path/**/*.java)
49
+ A extension pattern is allowd in the form %{pattern}
50
+ (ex some/path/*.{%{pattern1},%{pattern2}})
51
+ The globs support the following patterns:
52
+ %{cpp} - common C++ extensions
53
+
54
+ -g, --globfile A file with list of globs to perform (one per line)
55
+
56
+ -?, -h, --help Show this help message.
57
+ -v, --version Show the version number (#{VERSION})
58
+ -q, --quiet Don't log anything to stdout
59
+ -V, --verbose Show extra logging
60
+ -d, --dryrun Don't change any files on the filesystem
61
+ -c, --cache Specify the cache file for input and output.
62
+ [Default is .mtime_cache.json]
63
+
64
+ ENDHELP
65
+
66
+ param_arg = nil
67
+ ARGS = { :cache => '.mtime_cache.json', :globs => [] }
68
+
69
+ ARGV.each do |arg|
70
+ case arg
71
+ when '-g', '--globfile' then param_arg = :globfile
72
+ when '-h', '-?', '--help' then ARGS[:help] = true
73
+ when '-v', '--version' then ARGS[:ver] = true
74
+ when '-q', '--quiet' then ARGS[:quiet] = true
75
+ when '-V', '--verbose' then ARGS[:verbose] = true
76
+ when '-d', '--dryrun' then ARGS[:dry] = true
77
+ when '-c', '--cache' then param_arg = :cache
78
+ else
79
+ if param_arg
80
+ ARGS[param_arg] = arg
81
+ param_arg = nil
82
+ else
83
+ ARGS[:globs] << arg
84
+ end
85
+ end
86
+ end
87
+
88
+ def log(text, level = 0)
89
+ return if ARGS[:quiet]
90
+ return if level > 0 && !ARGS[:verbose]
91
+ puts text
92
+ end
93
+
94
+ if ARGS[:ver] || ARGS[:help]
95
+ log VERSION_TEXT
96
+ exit if ARGS[:ver]
97
+ log USAGE
98
+ log HELP
99
+ exit
100
+ end
101
+
102
+ if ARGS[:globs].empty? && !ARGS[:globfile]
103
+ log 'Error: Missing globs'
104
+ log USAGE
105
+ exit 1
106
+ end
107
+
108
+ EXTENSION_PATTERNS = {
109
+ :cpp => "c,cc,cpp,cxx,h,hpp,hxx,inl,ipp,inc,ixx"
110
+ }
111
+
112
+ cache_file = ARGS[:cache]
113
+
114
+ cache = {}
115
+
116
+ if File.file?(cache_file)
117
+ log "Found #{cache_file}"
118
+ cache = JSON.parse(File.read(cache_file))
119
+ log "Read #{cache.length} entries"
120
+ else
121
+ log "#{cache_file} not found. A new one will be created"
122
+ end
123
+
124
+ globs = ARGS[:globs].map { |g| g % EXTENSION_PATTERNS }
125
+
126
+ globfile = ARGS[:globfile]
127
+ File.open(globfile, 'r').each_line do |line|
128
+ line.strip!
129
+ next if line.empty?
130
+ globs << line % EXTENSION_PATTERNS
131
+ end
132
+
133
+ if globs.empty?
134
+ log 'Error: No globs in globfile'
135
+ log USAGE
136
+ exit 1
137
+ end
138
+
139
+ files = {}
140
+ num_changed = 0
141
+
142
+ globs.each do |glob|
143
+ Dir[glob].each do |file|
144
+ next if !File.file?(file)
145
+
146
+ mtime = File.mtime(file).to_i
147
+ hash = Digest::MD5.hexdigest(File.read(file))
148
+
149
+ cached = cache[file]
150
+
151
+ if cached && cached['hash'] == hash && cached['mtime'] < mtime
152
+ mtime = cached['mtime']
153
+
154
+ log "mtime_cache: changing mtime of #{file} to #{mtime}", 1
155
+
156
+ File.utime(File.atime(file), Time.at(mtime), file) if !ARGS[:dry]
157
+ num_changed += 1
158
+ else
159
+ log "mtime_cache: NOT changing mtime of #{file}", 1
160
+ end
161
+
162
+ files[file] = { 'mtime' => mtime, 'hash' => hash }
163
+ end
164
+ end
165
+
166
+ log "Changed mtime of #{num_changed} of #{files.length} files"
167
+ log "Writing #{cache_file}"
168
+
169
+ if !ARGS[:dry]
170
+ dirname = File.dirname(cache_file)
171
+ unless File.directory?(dirname)
172
+ FileUtils.mkdir_p(dirname)
173
+ end
174
+ File.open(cache_file, 'w').write(JSON.pretty_generate(files))
175
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mtime_cache
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Borislav Stanimirov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |
14
+ mtime_cache creates a cache of file modification times, based on a glob pattern.
15
+ If a cache exists it updates unchanged files (unchanged based on MD5 hash) with
16
+ the time from the cache.
17
+ This is useful if you cache your build artifacts for a build process which
18
+ detects changes based on source modification time (such as most C or C++ build
19
+ systems) on a continuous integration service (such as Travis CI), which clones
20
+ the repo for every build.
21
+ When the repo is cloned, all source files have a modification time equal to the
22
+ current time, making the cached build artifacts (for example .o files) obsolete.
23
+ mtime_cache allows you to cache the modification times of the files, enabling a
24
+ minimal rebuild for each clone.
25
+ email: b.stanimirov@abv.bg
26
+ executables:
27
+ - mtime_cache
28
+ extensions: []
29
+ extra_rdoc_files: []
30
+ files:
31
+ - bin/mtime_cache
32
+ homepage: https://github.com/iboB/mtime_cache
33
+ licenses:
34
+ - MIT
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubyforge_project:
52
+ rubygems_version: 2.5.1
53
+ signing_key:
54
+ specification_version: 4
55
+ summary: Cache file mtimes. Helps caching build artifacts on a CIS
56
+ test_files: []