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.
- checksums.yaml +7 -0
- data/bin/mtime_cache +175 -0
- 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: []
|