license_header 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # LicenseHeader
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'license_header'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install license_header
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'license_header'
4
+ require 'optparse'
5
+ require 'highline/import'
6
+
7
+ command = nil
8
+ options = { :exceptions => [] }
9
+
10
+ @prompt = true
11
+ def getYyn(text)
12
+ if @prompt
13
+ response = ask("#{text} (Y/y/n) ") { |q|
14
+ q.overwrite = true
15
+ q.echo = true
16
+ q.character = true
17
+ q.validate { |r| r =~ /^[Yyn]$/ }
18
+ }
19
+ if response == 'Y'
20
+ @prompt = false
21
+ end
22
+ return response.downcase == 'y'
23
+ else
24
+ return true
25
+ end
26
+ end
27
+
28
+ opts = OptionParser.new do |opts|
29
+ opts.banner = "Usage: #{File.basename $0} <action> [options] <filespec>"
30
+
31
+ opts.separator 'Actions:'
32
+
33
+ opts.on('-a', '--audit', "Print a list of files needing license updates") do
34
+ command = :audit
35
+ end
36
+
37
+ opts.on('-u', '--update', "Update files requiring license headers") do
38
+ command = :update
39
+ end
40
+
41
+ opts.on('-r', '--remove', "Remove license headers from files") do
42
+ command = :remove
43
+ end
44
+
45
+ opts.separator 'Common options:'
46
+
47
+ opts.on('-f FILE', '--header-file=FILE', "File containing header text") do |arg|
48
+ options[:header] = arg
49
+ end
50
+
51
+ opts.on('-x MASK', '--exclude=MASK', "Exclude pattern") do |arg|
52
+ pattern = Regexp.escape(arg).gsub('\*','.*?')
53
+ re = /^#{pattern}$/i
54
+ options[:exceptions] << re
55
+ end
56
+
57
+ opts.on('-y', '--yes', "Assume yes reponses to all prompts") do
58
+ @prompt = false
59
+ end
60
+
61
+ opts.on('-v', '--verbose', "Run verbosely") do
62
+ options[:verbose] = true
63
+ end
64
+
65
+ opts.on_tail('-h', '--help', "Show this message") do
66
+ puts opts
67
+ exit
68
+ end
69
+ end
70
+ opts.parse!
71
+
72
+ if command.nil? or options[:header].nil? or ARGV.empty?
73
+ puts opts
74
+ exit
75
+ end
76
+
77
+ targets = ARGV.collect do |spec|
78
+ File.directory?(spec) ? File.join(spec,"**","*") : spec
79
+ end
80
+
81
+ auditor = LicenseHeader::Auditor.new(options)
82
+ files = auditor.audit(*targets)
83
+ invalid = (files[:missing]+files[:invalid]).sort
84
+ present = (files[:present]+files[:valid]).sort
85
+ case command
86
+ when :audit
87
+ $stderr.puts "#{files[:valid].length} files have correct headers"
88
+ $stderr.puts files[:valid].join("\n") if options[:verbose]
89
+ $stderr.puts "#{files[:missing].length} files have missing headers"
90
+ $stderr.puts files[:missing].join("\n") if options[:verbose]
91
+ $stderr.puts "#{files[:invalid].length} files have invalid headers"
92
+ $stderr.puts files[:invalid].join("\n") if options[:verbose]
93
+ when :update
94
+ $stderr.puts "#{invalid.length} files have missing or incorrect headers"
95
+ auditor.process_files(:update, * invalid) do |file, format|
96
+ response = getYyn("Update header in #{file}?")
97
+ $stderr.puts "Updating #{file}..." if response
98
+ response
99
+ end
100
+ when :remove
101
+ $stderr.puts "#{present.length} files have headers"
102
+ auditor.process_files(:remove, *present) do |file, format|
103
+ response = getYyn("Remove header from #{file}?")
104
+ $stderr.puts "Cleaning up #{file}..." if response
105
+ response
106
+ end
107
+ end
@@ -0,0 +1,142 @@
1
+ require 'fileutils'
2
+
3
+ # Module to assist in making sure that all files have the right license
4
+ # block as a header.
5
+
6
+ module LicenseHeader
7
+ # For each language you can define three variables
8
+ #
9
+ # :pre will be prepended to the header
10
+ # :each will be prepended to each line of the header
11
+ # :post will be appended to the end of the file
12
+ #
13
+ # Only :each is required; if the other two are not provided they will be
14
+ # ignored
15
+ LANGUAGE_SYNTAX = {
16
+ :css => { :pre => '/* ', :each => ' * ', :post => '*/', :exts => %w(.css .scss) },
17
+ :erb => { :pre => '<%#', :each => '', :post => '%>', :exts => %w(.erb) },
18
+ :haml => { :pre => '-#', :each => ' ', :exts => %w(.haml) },
19
+ :html => { :pre => '<!--', :each => '', :post => '-->', :exts => %w(.html) },
20
+ :javascript => { :pre => '/* ', :each => ' * ', :post => '*/', :exts => %w(.js .json) },
21
+ :ruby => { :each => '# ', :exts => %w(.rb .rake .coffee) },
22
+ }
23
+
24
+ class Auditor
25
+ attr_accessor :exceptions, :header, :verbose
26
+
27
+ # Should set some sensible defaults here for license location, file
28
+ # mappings, etc
29
+ def initialize(configuration)
30
+ @verbose = configuration[:verbose]
31
+ @header = configuration[:header]
32
+ @exceptions = configuration[:exceptions]
33
+ initialize_headers
34
+ end
35
+
36
+ # Create a list of all files grouped by type and return the map
37
+ def audit(*patterns)
38
+ result = Hash.new { |h,k| h[k] = [] }
39
+
40
+ Dir.glob(patterns).each do |entry|
41
+ # Skip directories and files that match the exceptions
42
+ next if File.directory?(entry)
43
+ if @exceptions.any? { |ex| ex.match(entry) }
44
+ $stderr.puts "Skipping #{entry}" if @verbose
45
+ next
46
+ end
47
+
48
+ # Now to get down to business
49
+ format = determine_format(entry)
50
+ result[evaluate_header(entry, format)] << entry
51
+ end
52
+
53
+ return result
54
+ end
55
+
56
+ def evaluate_header(path, format)
57
+ if format.nil? or format[:header].nil?
58
+ :not_applicable
59
+ else
60
+ file_content = read_file(path)
61
+ header_content = format[:header]
62
+ index = file_content.find_index { |l| l =~ /--- [E]ND AVALON LICENSE BLOCK ---/ }
63
+ if index.nil?
64
+ :missing
65
+ else
66
+ file_heading = file_content[0, header_content.size]
67
+ if file_heading.eql? header_content
68
+ :valid
69
+ else
70
+ :present
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ def process_files(action, *files)
77
+ files.each do |file|
78
+ format = determine_format(file)
79
+ source_file = read_file(file)
80
+ confirm = block_given? ? yield(file) : true
81
+ if confirm and self.send(:"#{action.to_s}_license!", source_file, format)
82
+ write_file(file, source_file)
83
+ end
84
+ end
85
+ end
86
+
87
+ def update_license!(source_file, format)
88
+ remove_license!(source_file, format)
89
+ header_content = format[:header]
90
+ header_content.reverse.each { |line| source_file.insert(0, line) }
91
+ return true
92
+ end
93
+
94
+ def remove_license!(source_file, format)
95
+ end_of_license = source_file.find_index { |l| l =~ /--- [E]ND AVALON LICENSE BLOCK ---/ }
96
+ if end_of_license.nil?
97
+ return false
98
+ else
99
+ extra_lines = format[:post].nil? ? 1 : 2
100
+ source_file.shift(end_of_license+extra_lines+1)
101
+ return true
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ def determine_format(file)
108
+ @headers.values.find { |syntax| syntax[:exts].include?(File.extname(file)) }
109
+ end
110
+
111
+ def read_file(file)
112
+ File.read(file).chomp.split(/\n/)
113
+ end
114
+
115
+ def write_file(file, content)
116
+ File.open("#{file}.tmp", "w") { |tmpfile| tmpfile.puts(content.join("\n")) }
117
+ FileUtils.rm(file)
118
+ FileUtils.mv("#{file}.tmp", file)
119
+ end
120
+
121
+ # Here we need to take the stock header and create two different versions -
122
+ # one for Ruby based content using the # notation and another for
123
+ # Javascript that uses /* */ syntax
124
+ def initialize_headers
125
+ @headers = LANGUAGE_SYNTAX.clone
126
+ base = File.read(@header)
127
+ # Break each line down so we can do easy manipulation to create our new
128
+ # versions
129
+ license_terms = base.split(/\n/)
130
+
131
+ @headers.each_pair do |lang,syntax|
132
+ syntax[:header] = []
133
+ syntax[:header] << syntax[:pre] unless syntax[:pre].nil?
134
+ syntax[:header] << "#{syntax[:each]} --- BEGIN AVALON LICENSE BLOCK ---"
135
+ syntax[:header] += license_terms.collect {|line| syntax[:each] + line }
136
+ syntax[:header] << "#{syntax[:each]} --- #{'E'}ND AVALON LICENSE BLOCK ---"
137
+ syntax[:header] << syntax[:post] unless syntax[:post].nil?
138
+ syntax[:header] << ""
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,3 @@
1
+ module LicenseHeader
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,6 @@
1
+ require "license_header/version"
2
+ require "license_header/auditor"
3
+
4
+ module LicenseHeader
5
+ # Your code goes here...
6
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: license_header
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nathan Rogers
9
+ - Michael Klein
10
+ - Chris Colvard
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2013-04-18 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: highline
18
+ requirement: !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ! '>='
30
+ - !ruby/object:Gem::Version
31
+ version: '0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: bundler
34
+ requirement: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: '1.3'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ - !ruby/object:Gem::Dependency
49
+ name: rake
50
+ requirement: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ description: License header block auditing/updating
65
+ email:
66
+ - rogersna@indiana.edu
67
+ executables:
68
+ - license_header
69
+ extensions: []
70
+ extra_rdoc_files: []
71
+ files:
72
+ - lib/license_header/auditor.rb
73
+ - lib/license_header/version.rb
74
+ - lib/license_header.rb
75
+ - bin/license_header
76
+ - README.md
77
+ homepage:
78
+ licenses: []
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ segments:
90
+ - 0
91
+ hash: 3735959797291095628
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ segments:
99
+ - 0
100
+ hash: 3735959797291095628
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 1.8.23
104
+ signing_key:
105
+ specification_version: 3
106
+ summary: This gem will assist in making sure that all files have the right license
107
+ block as a header.
108
+ test_files: []