code-tools 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5bccd6fecbea6c93c32b92522d03fc000ebe403b
4
+ data.tar.gz: 927adb322732ca9f2f37cff0372d0f5c215810be
5
+ SHA512:
6
+ metadata.gz: 596b5fec512b56871f04ed48d2633fd567ba80efa53c7b2bb5732b92643d707e8b8dcf76651dcea097b3323a8b212f0f6957ace5fef32ea9a543c780b8b83bd1
7
+ data.tar.gz: e9335f94a397cc1333d31aa0bd3df41fb3aa282840f1e50c39f07bfd67091d600d25572c0db1e9e59a7a8f72b312b0d5c14c4b5fd44a904aba874aa1e053a80b
data/bin/code-tools ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ puts "vamper - Version stamper"
3
+ puts "ender - CR/LF line ending fixer"
4
+ puts "spacer - Space/tab line fixer"
data/bin/ender ADDED
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'methadone'
6
+
7
+ class Tool
8
+ include Methadone::Main
9
+ include Methadone::CLILogging
10
+
11
+ main do |input_file|
12
+ unless File.exist?(input_file)
13
+ error "File #{input_file} does not exist"
14
+ next 1
15
+ end
16
+
17
+ output_file = options[:output_file]
18
+
19
+ if output_file.nil?
20
+ output_file = input_file
21
+ end
22
+
23
+ # Read the entire file and determine all the different line endings
24
+ file_contents = IO.read(input_file)
25
+ num_cr = 0
26
+ num_lf = 0
27
+ num_crlf = 0
28
+ num_lines = 1
29
+
30
+ i = 0
31
+ while i < file_contents.length do
32
+ c = file_contents[i]
33
+
34
+ if c == "\r"
35
+ if i < file_contents.length - 1 and file_contents[i + 1] == "\n"
36
+ num_crlf += 1
37
+ i += 1
38
+ else
39
+ num_cr += 1
40
+ end
41
+
42
+ num_lines += 1
43
+ elsif c == "\n"
44
+ num_lf += 1
45
+ num_lines += 1
46
+ end
47
+ i += 1
48
+ end
49
+
50
+ num_endings = (num_cr > 0 ? 1 : 0) + (num_lf > 0 ? 1 : 0) + (num_crlf > 0 ? 1 : 0)
51
+ le = num_endings > 1 ? :mixed : num_cr > 0 ? :cr : num_lf > 0 ? :lf : :crlf
52
+ msg = "\"#{input_file}\", #{le.to_s}, #{num_lines} lines"
53
+
54
+ if options[:mode].nil?
55
+ info msg
56
+ next 1
57
+ end
58
+
59
+ if options[:mode] == :auto
60
+ # Find the most common line ending and make that the automatic line ending
61
+ auto_line_ending = :lf
62
+ n = num_lf
63
+
64
+ if num_crlf > n
65
+ auto_line_ending = :crlf
66
+ n = num_crlf
67
+ end
68
+
69
+ if num_cr > n
70
+ auto_line_ending = :cr
71
+ end
72
+
73
+ options[:mode] = auto_line_ending
74
+ end
75
+
76
+ new_num_lines = 1
77
+
78
+ if (options[:mode] == :cr and num_cr + 1 == num_lines) or
79
+ (options[:mode] == :lf and num_lf + 1 == num_lines) or
80
+ (options[:mode] == :crlf and num_crlf + 1 == num_lines)
81
+ # We're not changing the line endings; nothing to do
82
+ new_num_lines = num_lines
83
+ else
84
+ newline_chars =
85
+ options[:mode] == :cr ? "\r" :
86
+ options[:mode] == :lf ? "\n" :
87
+ "\r\n"
88
+
89
+ file = nil
90
+
91
+ begin
92
+ file = File.new(output_file, 'w')
93
+
94
+ i = 0
95
+ while i < file_contents.length
96
+ c = file_contents[i]
97
+
98
+ if c == "\r"
99
+ if i < file_contents.length - 1 && file_contents[i + 1] == "\n"
100
+ i += 1
101
+ end
102
+
103
+ new_num_lines += 1
104
+ file.write(newline_chars)
105
+ elsif c == "\n"
106
+ new_num_lines += 1
107
+ file.write(newline_chars)
108
+ else
109
+ file.write(c)
110
+ end
111
+
112
+ i += 1
113
+ end
114
+ rescue Exception => e
115
+ error "unable to write #{output_file}. #{e.to_s}"
116
+ next 1
117
+ ensure
118
+ file.close() unless !file
119
+ end
120
+
121
+ msg += " -> \"#{output_file}\", #{options[:mode].to_s}, #{new_num_lines} lines"
122
+ end
123
+
124
+ info msg
125
+ end
126
+
127
+ change_logger Methadone::CLILogger.new
128
+
129
+ description 'Ender - the line ending fixer'
130
+ version '5.0.0'
131
+
132
+ on("-o", "--output-file FILE", "The output file. Default is the same as the input file.")
133
+ on("-m", "--mode MODE",
134
+ "The convert mode, either auto, cr, lf, crlf. auto will use the most commonly occurring ending. "\
135
+ "Updates will only be done when this argument is given.") do |mode|
136
+ options[:mode] = case mode
137
+ when 'auto', 'a'
138
+ :auto
139
+ when 'lf'
140
+ :lf
141
+ when 'cr'
142
+ :cr
143
+ when 'crlf'
144
+ :crlf
145
+ else
146
+ exit_now! "Unknown mode #{mode}"
147
+ end
148
+ end
149
+
150
+ arg :input_file, "Input file to check or convert"
151
+
152
+ go!
153
+ end
data/bin/spacer ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'methadone'
6
+ require 'spacer'
7
+
8
+ class Tool
9
+ include Methadone::Main
10
+ include Methadone::CLILogging
11
+
12
+ # When reporting the tool indicates beginning-of-line \(BOL\) tabs and spaces.
13
+ # When replacing, all tabs not at the beginning of a line are replaced with spaces.
14
+ # Spaces and tabs inside multi-line C# strings (@"...") and inside Ruby \%Q\(...\) strings
15
+ # are ignored.
16
+ # Note that conversion to tabs may still leave the file as mixed as some lines may have
17
+ # spaces that are not a whole number multiple of the tabstop size. In that case use the
18
+ # -round option to remove smooth out the spurious spaces.
19
+
20
+ def self.get_whitespace_type(bol)
21
+ (bol.tabs > 0) ? (bol.spaces > 0 ? :mixed : :tabs) : :spaces
22
+ end
23
+
24
+ def self.read_file_lines(filename)
25
+ # Read the entire file
26
+ file_contents = File.read(filename)
27
+
28
+ # Convert to a list of lines, preserving the end-of-lines
29
+ lines = []
30
+ s = 0
31
+ i = 0
32
+
33
+ while i < file_contents.length do
34
+ c = file_contents[i]
35
+ c1 = i < file_contents.length - 1 ? file_contents[i + 1] : "\0"
36
+
37
+ if c == "\r"
38
+ i += 1
39
+
40
+ if c1 == "\n"
41
+ i += 1
42
+ end
43
+ elsif c == "\n"
44
+ i += 1
45
+ else
46
+ i += 1
47
+ next
48
+ end
49
+
50
+ lines.push(file_contents[s, i - s])
51
+ s = i
52
+ end
53
+
54
+ if s != i
55
+ lines.push(file_contents[s, i - s])
56
+ end
57
+
58
+ lines
59
+ end
60
+
61
+ main do |input_file|
62
+ unless File.exist?(input_file)
63
+ error "File #{input_file} does not exist"
64
+ next 1
65
+ end
66
+
67
+ output_file = options[:output_file]
68
+
69
+ if output_file.nil?
70
+ output_file = input_file
71
+ end
72
+
73
+ if File.extname(input_file) == '.cs'
74
+ file_type = :csharp
75
+ else
76
+ file_type = :text
77
+ end
78
+
79
+ lines = read_file_lines(input_file)
80
+
81
+ if file_type == :text
82
+ before = Spacer::Text.count_bol_spaces_and_tabs(lines)
83
+ else
84
+ before = Spacer::CSharp.count_bol_spaces_and_tabs(lines)
85
+ end
86
+
87
+ if !options[:mode].nil?
88
+ if file_type == :text
89
+ Spacer::Text.untabify(lines, options[:tabsize])
90
+ else
91
+ Spacer::CSharp.untabify(lines, options[:tabsize])
92
+ end
93
+
94
+ if options[:mode] == :tabs
95
+ if file_type == :text
96
+ Spacer::Text.tabify(lines, options[:tabsize], options[:round])
97
+ else
98
+ Spacer::CSharp.tabify(lines, options[:tabsize], options[:round])
99
+ end
100
+ end
101
+ end
102
+
103
+ msg = "\"#{input_file}\", #{file_type.to_s}, #{get_whitespace_type(before).to_s}"
104
+
105
+ if !options[:mode].nil?
106
+ if file_type == :text
107
+ after = Spacer::Text.count_bol_spaces_and_tabs(lines)
108
+ else
109
+ after = Spacer::CSharp.count_bol_spaces_and_tabs(lines)
110
+ end
111
+
112
+ file = nil
113
+
114
+ begin
115
+ file = File.new(output_file, 'w')
116
+
117
+ for line in lines do
118
+ file.write(line)
119
+ end
120
+ ensure
121
+ file.close() unless file == nil
122
+ end
123
+
124
+ msg += " -> \"#{output_file}\", #{get_whitespace_type(after).to_s}"
125
+ end
126
+
127
+ info msg
128
+ end
129
+
130
+ description 'Spacer - source file space/tab fixer tool'
131
+ version '5.0.0'
132
+
133
+ options[:tabsize] = 4
134
+ options[:round] = false
135
+
136
+ on("-o", "--output-file FILE", "The output file. Default is the same as the input file.")
137
+ on("-m", "--mode MODE","The convert mode (tabs or spaces) Default is to just display the files current state."\
138
+ "Updates will only be done when this argument is given.") do |mode|
139
+ options[:mode] = case mode
140
+ when 'tabs', 't'
141
+ :tabs
142
+ when 'spaces', 's'
143
+ :spaces
144
+ else
145
+ exit_now! "Unknown mode #{mode}"
146
+ end
147
+ end
148
+ on("-t", "--tabsize TABSIZE", "Tab size in spaces to assume. Default is #{options[:tabsize]} spaces.")
149
+ on("-r", "--round", "When tabifying, round BOL spaces down to an exact number of tabs.")
150
+
151
+ arg :input_file, "Input file to check or convert"
152
+
153
+ go!
154
+ end
data/bin/vamper ADDED
@@ -0,0 +1,180 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'methadone'
6
+ require 'vamper'
7
+ require 'tzinfo'
8
+
9
+ class Tool
10
+ include Methadone::Main
11
+ include Methadone::CLILogging
12
+
13
+ def self.find_version_file()
14
+ dir = Dir.pwd
15
+
16
+ while dir.length != 0
17
+ files = Dir.glob('*.version')
18
+ if files.length > 0
19
+ file = files[0]
20
+ break
21
+ else
22
+ if dir == '/'
23
+ dir = ''
24
+ else
25
+ dir = File.expand_path('..', dir)
26
+ end
27
+ end
28
+ end
29
+
30
+ if file.nil?
31
+ exit_now! 'Unable to find a .version file in this or parent directories.'
32
+ end
33
+
34
+ file
35
+ end
36
+
37
+ def self.get_full_date(now)
38
+ now.year * 10000 + now.month * 100 + now.mday
39
+ end
40
+
41
+ def get_jdate(now, start_year)
42
+ (((now.year - start_year + 1) * 10000) + (now.month * 100) + now.mday).to_s
43
+ end
44
+
45
+ main do |input_file|
46
+ if input_file.nil? or !File.exist?(input_file)
47
+ input_file = find_version_file
48
+ end
49
+
50
+ input_file = File.expand_path(input_file)
51
+
52
+ project_name = File.basename(input_file, '.version')
53
+ version_config_file_name = "#{File.dirname(input_file)}/#{project_name}.version.config"
54
+
55
+ info "Version file is '#{input_file}'"
56
+ info "Version config is '#{version_config_file_name}'"
57
+ info "Project name is '#{project_name}'"
58
+
59
+ if File.exists?(input_file)
60
+ version_data = Vamper::VersionFile.new(File.open(input_file))
61
+ else
62
+ version_data = Vamper::VersionFile.new
63
+ end
64
+
65
+ now = TZInfo::Timezone.get(version_data.time_zone).now
66
+
67
+ case version_data.build_value_type
68
+ when :JDate
69
+ build = get_jdate(now, version_data.start_year)
70
+
71
+ if version_data.build != build
72
+ version_data.revision = 0
73
+ version_data.build = build
74
+ else
75
+ version_data.revision += 1
76
+ end
77
+ when :Incremental
78
+ version_data.build += 1
79
+ version_data.revision = 0
80
+ else # :FullDate
81
+ build = get_full_date(now)
82
+
83
+ if version_data.build != build
84
+ version_data.revision = 0
85
+ version_data.build = build
86
+ else
87
+ version_data.revision += 1
88
+ end
89
+ end
90
+
91
+ tags = version_data.tags
92
+
93
+ case version_data.build_value_type
94
+ when :FullDate
95
+ build_str = build.to_s
96
+ tags[:DashBuild] = build_str[0..3] + '-' + build_str[4..5] + '-' + build_str[6..7]
97
+ end
98
+
99
+ info 'Version tags are:'
100
+ tags.each { |key, value|
101
+ info " #{key}=#{value}"
102
+ }
103
+
104
+ if options[:update]
105
+ info 'Updating version information:'
106
+ end
107
+
108
+ unless File.exists?(version_config_file_name)
109
+ FileUtils.cp(Vamper::VersionConfigFile.get_default_file, version_config_file_name)
110
+ end
111
+
112
+ version_config_file = Vamper::VersionConfigFile.new(File.open(version_config_file_name), tags)
113
+ file_list = version_data.files.map { |file_name| file_name.replace_tags!(tags) }
114
+
115
+ file_list.each do |file_name|
116
+ path = File.expand_path(File.join(File.dirname(input_file), file_name))
117
+ path_file_name = File.basename(path)
118
+ match = false
119
+
120
+ for file_type in version_config_file.file_types do
121
+ match = file_type.file_specs.any? { |file_spec| file_spec.match(path_file_name) }
122
+ unless match
123
+ next
124
+ end
125
+
126
+ if file_type.write
127
+ dir = File.dirname(path)
128
+ unless Dir.exists?(dir)
129
+ error "Directory '#{dir}' does not exist to write file ''#{path_file_name}''"
130
+ exit(1)
131
+ end
132
+
133
+ if options[:update]
134
+ IO.write(path, file_type.write)
135
+ end
136
+ else # !file_type.write
137
+ if File.exists?(path)
138
+ if options[:update]
139
+ file_type.updates.each do |update|
140
+ content = IO.read(path)
141
+ # At this point the only ${...} variables left in the replace strings are Before and After
142
+ # This line converts the ${...} into \k<...> to put captured groups from search back
143
+ # into the replace string.
144
+ content.gsub!(%r(#{update.search})m, update.replace.gsub(/\${(\w+)}/,'\\\\k<\\1>'))
145
+ IO.write(path, content)
146
+ end
147
+ end
148
+ else
149
+ error "file #{path} does not exist to update"
150
+ exit(1)
151
+ end
152
+ end
153
+
154
+ break
155
+ end
156
+
157
+ unless match
158
+ error "file '#{path}' has no matching file type in the .version.config"
159
+ exit(1)
160
+ end
161
+
162
+ info path
163
+
164
+ if options[:update]
165
+ version_data.write_to(File.open(input_file, 'w'))
166
+ end
167
+ end
168
+ end
169
+
170
+ description 'Vamper - file version stamper'
171
+ version '5.0.0'
172
+
173
+ options[:update] = false
174
+
175
+ on("-u", "--update", "Actually do the update.")
176
+
177
+ arg :input_file, "A version file. Default is to search parent directories for *.version", :optional
178
+
179
+ go!
180
+ end
data/lib/core_ext.rb ADDED
@@ -0,0 +1,54 @@
1
+ class String
2
+ def underscore
3
+ self.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
6
+ tr('-', '_').
7
+ downcase
8
+ end
9
+
10
+ def replace_tags(tags)
11
+ str = self
12
+ tags.each { |name, value|
13
+ str = str.gsub(%r(\$\{#{name.to_s}\})m, value)
14
+ }
15
+ str
16
+ end
17
+
18
+ def replace_tags!(tags)
19
+ tags.each { |name, value|
20
+ self.gsub!(%r(\$\{#{name.to_s}\})m, value)
21
+ }
22
+ self
23
+ end
24
+
25
+ # colorization
26
+ def colorize(color_code)
27
+ "\e[#{color_code}m#{self}\e[0m"
28
+ end
29
+
30
+ def red
31
+ colorize(31)
32
+ end
33
+
34
+ def green
35
+ colorize(32)
36
+ end
37
+
38
+ def yellow
39
+ colorize(33)
40
+ end
41
+
42
+ def blue
43
+ colorize(34)
44
+ end
45
+
46
+ def pink
47
+ colorize(35)
48
+ end
49
+
50
+ def light_blue
51
+ colorize(36)
52
+ end
53
+
54
+ end
@@ -0,0 +1,142 @@
1
+ require 'ostruct'
2
+
3
+ module Spacer
4
+ module CSharp
5
+ def self.count_bol_spaces_and_tabs(lines)
6
+ bol = OpenStruct.new
7
+ bol.tabs = 0
8
+ bol.spaces = 0
9
+ in_multi_line_string = false
10
+
11
+ for line in lines do
12
+ in_bol = true
13
+ i = 0
14
+ while i < line.length do
15
+ c = line[i]
16
+ c1 = i < line.length - 1 ? line[i + 1] : "\0"
17
+
18
+ if in_multi_line_string and c == "\"" and c1 != "\""
19
+ in_multi_line_string = false
20
+ elsif c == "@" and c1 == "\""
21
+ in_multi_line_string = true
22
+ i += 1
23
+ elsif in_bol and !in_multi_line_string and c == " "
24
+ bol.spaces += 1
25
+ elsif in_bol and !in_multi_line_string and c == "\t"
26
+ bol.tabs += 1
27
+ else
28
+ in_bol = false
29
+ end
30
+ i += 1
31
+ end
32
+ end
33
+
34
+ bol
35
+ end
36
+
37
+ def self.untabify(lines, tabsize)
38
+ # Expand tabs anywhere on a line, but not inside @"..." strings
39
+ in_multi_line_string = false
40
+
41
+ i = 0
42
+ while i < lines.length do
43
+ line = lines[i]
44
+ in_string = false
45
+ new_line = ""
46
+ j = 0
47
+
48
+ while j < line.length do
49
+ c_1 = j > 0 ? line[j - 1] : '\0'
50
+ c = line[j]
51
+ c1 = j < line.length - 1 ? line[j + 1] : '\0'
52
+
53
+ raise "line #{i + 1} has overlapping regular and multiline strings" if (in_string and in_multi_line_string)
54
+
55
+ if !in_multi_line_string and c == "\t"
56
+ # Add spaces to next tabstop
57
+ num_spaces = tabsize - (new_line.length % tabsize)
58
+
59
+ new_line += " " * num_spaces
60
+ elsif !in_multi_line_string and !in_string and c == "\""
61
+ in_string = true
62
+ new_line += c
63
+ elsif !in_multi_line_string and !in_string and c == "@" and c1 == "\""
64
+ in_multi_line_string = true
65
+ new_line += c
66
+ j += 1
67
+ new_line += c1
68
+ elsif in_string and c == "\"" and c_1 != "\\"
69
+ in_string = false
70
+ new_line += c
71
+ elsif in_multi_line_string and c == "\"" and c1 != "\""
72
+ in_multi_line_string = false
73
+ new_line += c
74
+ else
75
+ new_line += c
76
+ end
77
+
78
+ lines[i] = new_line
79
+ j += 1
80
+ end
81
+ i += 1
82
+ end
83
+ end
84
+
85
+ def self.tabify(lines, tabsize, round_down_spaces)
86
+ # Insert tabs for spaces, but only at the beginning of lines and not inside @"..." or "..." strings
87
+ in_multi_line_string = false
88
+ i = 0
89
+
90
+ while i < lines.length do
91
+ line = lines[i]
92
+ in_string = false
93
+ bol = true
94
+ num_bol_spaces = 0
95
+ new_line = ""
96
+ j = 0
97
+
98
+ while j < line.length do
99
+ c_1 = j > 0 ? line[j - 1] : "\0"
100
+ c = line[j]
101
+ c1 = j < line.length - 1 ? line[j + 1] : "\0"
102
+
103
+ if !in_string and !in_multi_line_string and bol and c == " "
104
+ # Just count the spaces
105
+ num_bol_spaces += 1
106
+ elsif !in_string and !in_multi_line_string and bol and c != " "
107
+ bol = false
108
+
109
+ new_line += "\t" * (num_bol_spaces / tabsize)
110
+
111
+ if !round_down_spaces
112
+ new_line += " " * (num_bol_spaces % tabsize)
113
+ end
114
+ # Process this character again as not BOL
115
+ j -= 1
116
+ elsif !in_multi_line_string and !in_string and c == '"'
117
+ in_string = true
118
+ new_line += c
119
+ elsif !in_multi_line_string and !in_string and c == "@" and c1 == "\""
120
+ in_multi_line_string = true
121
+ new_line += c
122
+ j += 1
123
+ new_line += c1
124
+ elsif in_string and c == "\"" and c_1 != "\\"
125
+ in_string = false
126
+ new_line += c
127
+ elsif in_multi_line_string and c == "\"" and c1 != "\""
128
+ in_multi_line_string = false
129
+ new_line += c
130
+ else
131
+ new_line += c
132
+ end
133
+
134
+ lines[i] = new_line
135
+ j += 1
136
+ end
137
+ i += 1
138
+ end
139
+ end
140
+
141
+ end
142
+ end
@@ -0,0 +1,85 @@
1
+ module Spacer
2
+ module Text
3
+ def self.count_bol_spaces_and_tabs(lines)
4
+ bol = OpenStruct.new
5
+ bol.spaces = 0
6
+ bol.tabs = 0
7
+
8
+ for line in lines do
9
+ for i in 0...line.length do
10
+ c = line[i]
11
+
12
+ if c == " "
13
+ bol.spaces += 1
14
+ elsif c == "\t"
15
+ bol.tabs += 1
16
+ else
17
+ break
18
+ end
19
+ end
20
+ end
21
+
22
+ bol
23
+ end
24
+
25
+ def self.untabify(lines, tabsize)
26
+ i = 0
27
+ while i < lines.length do
28
+ line = lines[i]
29
+ j = 0
30
+ new_line = ""
31
+
32
+ while j < line.length do
33
+ c = line[j]
34
+
35
+ if c == "\t"
36
+ num_spaces = tabsize - (new_line.length % tabsize)
37
+ new_line += " " * num_spaces
38
+ else
39
+ new_line += c
40
+ end
41
+ j += 1
42
+ end
43
+
44
+ lines[i] = new_line
45
+ i += 1
46
+ end
47
+ end
48
+
49
+ def self.tabify(lines, tabsize, round_down_spaces)
50
+ i = 0
51
+ while i < lines.length do
52
+ line = lines[i]
53
+ j = 0
54
+ bol = true
55
+ num_bol_spaces = 0
56
+ new_line = ""
57
+
58
+ while j < line.length do
59
+ c = line[j]
60
+
61
+ if bol and c == " "
62
+ num_bol_spaces += 1
63
+ elsif bol and c != " "
64
+ bol = false
65
+ new_line += "\t" * (num_bol_spaces / tabsize)
66
+
67
+ if !round_down_spaces
68
+ new_line += " " * (num_bol_spaces % tabsize)
69
+ end
70
+
71
+ new_line += c
72
+ else
73
+ new_line += c
74
+ end
75
+
76
+ j += 1
77
+ end
78
+
79
+ lines[i] = new_line
80
+ i += 1
81
+ end
82
+ end
83
+
84
+ end
85
+ end
data/lib/spacer.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'spacer/text'
2
+ require 'spacer/csharp'
@@ -0,0 +1,105 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <VersionConfig>
3
+ <FileType>
4
+ <Name>Ruby Files</Name>
5
+ <FileSpec>*.rb</FileSpec>
6
+ <Update>
7
+ <Search>(?'Before'\$VERSION=\')([0-9]+\.[0-9]+\.[0-9]+)-[0-9]+\.[0-9]+(?'After'\')</Search>
8
+ <Replace>${Before}${Major}.${Minor}.${Patch}-${Build}.${Revision}${After}</Replace>
9
+ </Update>
10
+ </FileType>
11
+ <FileType>
12
+ <Name>Version-in-a-text-file</Name>
13
+ <FileSpec>*.version.txt</FileSpec>
14
+ <Write>Release ${Major}.${Minor}.${Build}.${Revision}</Write>
15
+ </FileType>
16
+ <FileType>
17
+ <Name>Windows Manifest File</Name>
18
+ <FileSpec>WMManifest.xml</FileSpec>
19
+ <Update>
20
+ <Search>(?'Before'Version=")([0-9]+\.[0-9]+)(?'After'\.[0-9]+\.[0-9]+")</Search>
21
+ <Replace>${Before}${Major}.${Minor}${After}</Replace>
22
+ </Update>
23
+ </FileType>
24
+ <FileType>
25
+ <Name>C# Source</Name>
26
+ <FileSpec>*.cs</FileSpec>
27
+ <Update>
28
+ <Search>(?'Before'AssemblyVersion\(")([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'"\))</Search>
29
+ <Replace>${Before}${Major}.${Minor}.0.0${After}</Replace>
30
+ </Update>
31
+ <Update>
32
+ <Search>(?'Before'AssemblyFileVersion\(")([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'"\))</Search>
33
+ <Replace>${Before}${Major}.${Minor}.${Build}.${Revision}${After}</Replace>
34
+ </Update>
35
+ <Update>
36
+ <Search>(?'Before'AssemblyProduct\(")([^"]*)(?'After'"\))</Search>
37
+ <Replace>${Before}${Product}${After}</Replace>
38
+ </Update>
39
+ <Update>
40
+ <Search>(?'Before'AssemblyCopyright\(")([^"]*)(?'After'"\))</Search>
41
+ <Replace>${Before}${Copyright}${After}</Replace>
42
+ </Update>
43
+ <Update>
44
+ <Search>(?'Before'AssemblyCompany\(")([^"]*)(?'After'"\))</Search>
45
+ <Replace>${Before}${Company}${After}</Replace>
46
+ </Update>
47
+ </FileType>
48
+ <FileType>
49
+ <Name>Windows RC File</Name>
50
+ <FileSpec>*.rc</FileSpec>
51
+ <Update>
52
+ <Search>(?'Before'FILEVERSION )([0-9]+,[0-9]+,[0-9]+,[0-9]+)</Search>
53
+ <Replace>${Before}${Major},${Minor},${Build},${Revision}</Replace>
54
+ </Update>
55
+ <Update>
56
+ <Search>(?'Before'PRODUCTVERSION )([0-9]+,[0-9]+,[0-9]+,[0-9]+)</Search>
57
+ <Replace>${Before}${Major},${Minor},${Build},${Revision}</Replace>
58
+ </Update>
59
+ <Update>
60
+ <Search>(?'Before'"FileVersion",[ \t]*")([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'")</Search>
61
+ <Replace>${Before}${Major}.${Minor}.${Build}.${Revision}${After}</Replace>
62
+ </Update>
63
+ <Update>
64
+ <Search>(?'Before'"ProductVersion",[ \t]*")([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'")</Search>
65
+ <Replace>${Before}${Major}.${Minor}.${Build}.${Revision}${After}</Replace>
66
+ </Update>
67
+ </FileType>
68
+ <FileType>
69
+ <Name>WiX Files</Name>
70
+ <FileSpec>*.wxi</FileSpec>
71
+ <FileSpec>*.wxs</FileSpec>
72
+ <Update>
73
+ <Search>(?'Before'ProductVersion = ")([0-9]+\.[0-9]+)(?'After'")</Search>
74
+ <Replace>${Before}${Major}.${Minor}${After}</Replace>
75
+ </Update>
76
+ <Update>
77
+ <Search>(?'Before'ProductBuild = ")([0-9]+\.([0-9]|[1-9][0-9]))(?'After'")</Search>
78
+ <Replace>${Before}${Build}.${Revision}${After}</Replace>
79
+ </Update>
80
+ </FileType>
81
+ <FileType>
82
+ <Name>.NET Config Files</Name>
83
+ <FileSpec>*.config</FileSpec>
84
+ <Update>
85
+ <Search>(?'Before', +Version=)\d+\.\d+(?'After'\.0\.0 *,)</Search>
86
+ <Replace>${Before}${Major}.${Minor}${After}</Replace>
87
+ </Update>
88
+ </FileType>
89
+ <FileType>
90
+ <Name>Visual Studio Project Files</Name>
91
+ <FileSpec>*.csproj</FileSpec>
92
+ <Update>
93
+ <Search>(?'Before'&lt;OutputName&gt;" + projectName + @"_)([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'&lt;/OutputName&gt;)</Search>
94
+ <Replace>${Before}${Major}.${Minor}.${Build}.${Revision}${After}</Replace>
95
+ </Update>
96
+ </FileType>
97
+ <FileType>
98
+ <Name>VSIX Manifest</Name>
99
+ <FileSpec>*.vsixmanifest</FileSpec>
100
+ <Update>
101
+ <Search>(?'Before'&lt;Version&gt;)([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'&lt;/Version&gt;)</Search>
102
+ <Replace>${Before}${Major}.${Minor}.${Build}.${Revision}${After}</Replace>
103
+ </Update>
104
+ </FileType>
105
+ </VersionConfig>
@@ -0,0 +1,42 @@
1
+ require 'nokogiri'
2
+ require_relative '../core_ext.rb'
3
+
4
+ module Vamper
5
+ class VersionConfigFile
6
+
7
+ def self.get_default_file
8
+ File.join(File.dirname(__FILE__), 'default.version.config')
9
+ end
10
+
11
+ def initialize(io, tags)
12
+ doc = Nokogiri::XML(io)
13
+
14
+ @file_types = []
15
+ doc.xpath('/VersionConfig/FileType').each do |node|
16
+ file_type_struct = Struct.new(:name, :file_specs, :updates, :write)
17
+ search_replace_struct = Struct.new(:search, :replace)
18
+ file_type = file_type_struct.new
19
+ file_type.name = node.name
20
+ file_type.file_specs = node.xpath('FileSpec').map { |sub_node|
21
+ Regexp.new('^' + Regexp::escape(sub_node.text).gsub('\\*', '.*').gsub('\\?', '.') + '$')
22
+ }
23
+ update_node_set = node.xpath('Update')
24
+ if update_node_set
25
+ # Replace ${...} entries in the replace string with equivalent tags if available
26
+ file_type.updates = update_node_set.map { |sub_node|
27
+ s_and_r = search_replace_struct.new(
28
+ %r(#{sub_node.at_xpath('Search').text.gsub(/\(\?'(\w+)'/, '(?<\\1>')}),
29
+ sub_node.at_xpath('Replace').text.replace_tags(tags))
30
+ }
31
+ end
32
+ write_node = node.at_xpath('Write')
33
+ if write_node
34
+ file_type.write = write_node.text.replace_tags(tags)
35
+ end
36
+ @file_types.push(file_type)
37
+ end
38
+ end
39
+
40
+ attr_reader :file_types
41
+ end
42
+ end
@@ -0,0 +1,97 @@
1
+ require 'nokogiri'
2
+ require_relative '../core_ext.rb'
3
+
4
+ module Vamper
5
+ class BadVersionFile < StandardError; end
6
+
7
+ class VersionFile
8
+ attr_reader :tags
9
+
10
+ def initialize(io)
11
+ if io
12
+ @doc = Nokogiri::XML(io, &:noblanks)
13
+
14
+ unless @doc.root.name == 'Version'
15
+ raise BadVersionFile, 'Root element must be Version'
16
+ end
17
+ else
18
+ @doc = Nokogiri::XML::Document.new
19
+ @doc.root.add_child(Nokogiri::XML::Element.new('Version', @doc))
20
+ end
21
+
22
+ add_attribute @doc.root, :BuildValueType => :JDate
23
+ add_child_list_element @doc.root, :Files, :Tags
24
+ add_child_element tags_element,
25
+ :Major => 1, :Minor => 0, :Build => 0, :Patch => 0, :Revision => 0, :TimeZone => 'UTC'
26
+ add_child_element tags_element, {:StartYear => TZInfo::Timezone.get(self.time_zone).now.year}
27
+ end
28
+
29
+ def add_attribute(parent_node, attr_definitions)
30
+ attr_definitions.each { |attr_symbol, attr_default|
31
+ method_name = attr_symbol.to_s.underscore
32
+ unless parent_node[attr_symbol]
33
+ parent_node[attr_symbol] = attr_default
34
+ end
35
+ define_singleton_method(method_name.to_sym) {
36
+ parent_node[attr_symbol].to_sym
37
+ }
38
+ define_singleton_method((method_name + '=').to_sym) { |value|
39
+ parent_node[attr_symbol] = value.to_s
40
+ }
41
+ }
42
+ end
43
+
44
+ def add_child_list_element(parent_element, *element_symbols)
45
+ element_symbols.each { |element_symbol|
46
+ name = element_symbol.to_s
47
+ elem = parent_element.at(name)
48
+ unless elem
49
+ elem = parent_element.add_child(Nokogiri::XML::Element.new(name, @doc))
50
+ end
51
+
52
+ method_name = name.underscore + '_element'
53
+ define_singleton_method(method_name.to_sym) {
54
+ elem
55
+ }
56
+ }
57
+ end
58
+
59
+ def add_child_element(parent_element, element_definitions)
60
+ element_definitions.each { |element_symbol, element_default|
61
+ name = element_symbol.to_s
62
+ elem = parent_element.at(name)
63
+ unless elem
64
+ elem = parent_element.add_child(Nokogiri::XML::Element.new(name, @doc))
65
+ elem.content = element_default.to_s
66
+ end
67
+
68
+ method_name = name.underscore
69
+ case element_default
70
+ when Fixnum
71
+ define_singleton_method(method_name.to_sym) {
72
+ Integer(elem.content)
73
+ }
74
+ when String
75
+ define_singleton_method(method_name.to_sym) {
76
+ elem.content.to_s
77
+ }
78
+ end
79
+ define_singleton_method((method_name + '=').to_sym) { |value|
80
+ elem.content = value.to_s
81
+ }
82
+ }
83
+ end
84
+
85
+ def write_to(io)
86
+ @doc.write_xml_to(io, :indent_text => ' ', :indent => 2)
87
+ end
88
+
89
+ def tags
90
+ Hash[tags_element.children.select {|node| node.name != 'text'}.map {|node| [node.name.to_sym, node.content]}]
91
+ end
92
+ def files
93
+ files_element.children.select {|node| node.name != 'text'}.map {|node| node.content}
94
+ end
95
+
96
+ end
97
+ end
data/lib/vamper.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'vamper/version_file'
2
+ require 'vamper/version_config_file'
3
+ require 'core_ext.rb'
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: code-tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 5.0.0
5
+ platform: ruby
6
+ authors:
7
+ - John Lyon-smith
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tzinfo
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: methadone
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.9'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.9'
55
+ description: Tools for source code maintenance, including version stamping, line endings
56
+ and tab/space conversion.
57
+ email: john@jamoki.com
58
+ executables:
59
+ - code-tools
60
+ - ender
61
+ - spacer
62
+ - vamper
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - bin/code-tools
67
+ - bin/ender
68
+ - bin/spacer
69
+ - bin/vamper
70
+ - lib/core_ext.rb
71
+ - lib/spacer.rb
72
+ - lib/spacer/csharp.rb
73
+ - lib/spacer/text.rb
74
+ - lib/vamper.rb
75
+ - lib/vamper/default.version.config
76
+ - lib/vamper/version_config_file.rb
77
+ - lib/vamper/version_file.rb
78
+ homepage: http://rubygems.org/gems/code_tools
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '2.0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.4.5
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: Source code tools
102
+ test_files: []