Doing development in a side-file. Options and config files are now loaded sanely.
This commit is contained in:
parent
d2f2b3969b
commit
f9eedbb3e0
49
.git-lint
49
.git-lint
|
@ -1,68 +1,65 @@
|
||||||
[DEFAULT]
|
|
||||||
|
|
||||||
|
|
||||||
[debugging]
|
[debugging]
|
||||||
|
comment = Check to Ensure no debugger commands get checked in
|
||||||
output = Checking for debugger commands in Javascript...
|
output = Checking for debugger commands in Javascript...
|
||||||
command = grep -n debugger {filename}
|
command = grep -n debugger
|
||||||
files = [".*\.js$"]
|
files = .js
|
||||||
print = True
|
print = True
|
||||||
condition = output
|
condition = output
|
||||||
|
|
||||||
[jshint]
|
[jshint]
|
||||||
output = Running Jshint...
|
output = Running Jshint...
|
||||||
command = jshint -c {config_path}/jshint.rc {filename}
|
command = jshint -c %(repdir)s/.git-lint/jshint.rc
|
||||||
match = [".*\.js$"]
|
match = .js
|
||||||
print = False
|
print = False
|
||||||
condition = error
|
condition = error
|
||||||
|
|
||||||
[coffeelint]
|
[coffeelint]
|
||||||
output = Running Coffeelint...
|
output = Running Coffeelint...
|
||||||
command = coffeelint {filename}
|
command = coffeelint
|
||||||
match = [".*\.coffee$"]
|
match = .coffee
|
||||||
print = False
|
print = False
|
||||||
condition = error
|
condition = error
|
||||||
|
|
||||||
[jscs]
|
[jscs]
|
||||||
output = Running JSCS...
|
output = Running JSCS...
|
||||||
command = jscs -c {config_path}/jscs.rc {filename}
|
command = jscs -c %(repdir)s/.git-lint/jscs.rc
|
||||||
match = [".*\.js$"]
|
match = .js
|
||||||
print = False
|
print = False
|
||||||
condition = error
|
condition = error
|
||||||
|
|
||||||
[pep8]
|
[pep8]
|
||||||
|
comment = PEP8 with some white space and line length checking turned off
|
||||||
output = Running pep8...
|
output = Running pep8...
|
||||||
command = pep8 -r --ignore=E501,W293,W391 {filename}
|
command = pep8 -r --ignore=E501,W293,W391
|
||||||
match = [".*\.py$"]
|
match = .py
|
||||||
print = False
|
print = False
|
||||||
condition = error
|
condition = error
|
||||||
|
|
||||||
[xmllint]
|
[xmllint]
|
||||||
output = Running xmllint...
|
output = Running xmllint...
|
||||||
command = xmllint {filename}
|
command = xmllint
|
||||||
match = [".*\.xml"]
|
match = .xml
|
||||||
print = False
|
print = False
|
||||||
condition = error
|
condition = error
|
||||||
|
|
||||||
[flake8]
|
|
||||||
|
|
||||||
[csslint]
|
[csslint]
|
||||||
output = Running eslint...
|
output = Running csslint...
|
||||||
command = csslint --quiet --config={filename}
|
command = csslint --quiet
|
||||||
match = [".*\.js"]
|
match = .js
|
||||||
print = False
|
print = False
|
||||||
condition = error
|
condition = error
|
||||||
|
|
||||||
[eslint]
|
[eslint]
|
||||||
output = "Running eslint..."
|
output = Running eslint...
|
||||||
command = "eslint -c {filename}"
|
command = eslint
|
||||||
match = [".*\.js"]
|
match = .js
|
||||||
print = False
|
print = False
|
||||||
condition = error
|
condition = error
|
||||||
|
|
||||||
[jsonlint]
|
[jsonlint]
|
||||||
output = "Running jsonlint..."
|
output = Running jsonlint...
|
||||||
command = "jsonlint -q -c {filename}"
|
command = jsonlint -q
|
||||||
match = [".*\.json"]
|
match = .json
|
||||||
print = False
|
print = False
|
||||||
condition = error
|
condition = error
|
||||||
|
|
||||||
|
|
|
@ -27,22 +27,25 @@ Options
|
||||||
``-s`` ``--staging``
|
``-s`` ``--staging``
|
||||||
Check files in the staging area (useful as a pre-commit hook)
|
Check files in the staging area (useful as a pre-commit hook)
|
||||||
|
|
||||||
``-a`` ``--all``
|
|
||||||
Check all files in repository, not just changed files
|
|
||||||
|
|
||||||
``-b`` ``--base``
|
``-b`` ``--base``
|
||||||
Run checks from your repository's root directory. By default,
|
Run checks from your repository's root directory. By default,
|
||||||
``git-lint`` only runs from the current working directory.
|
``git-lint`` only runs from the current working directory.
|
||||||
|
|
||||||
|
``-a`` ``--all``
|
||||||
|
Check all files in repository from the current directory, not
|
||||||
|
just changed files
|
||||||
|
|
||||||
|
``-e`` ``--everything``
|
||||||
|
An alias for ``-b -a``, checks every file in the repository
|
||||||
|
|
||||||
``-o`` ``--only``
|
``-o`` ``--only``
|
||||||
Run only specific linters, skipping all others
|
Run only specific linters, skipping all others
|
||||||
|
|
||||||
``-e`` ``--exclude``
|
``-e`` ``--exclude``
|
||||||
Exclude specific linters, running all others
|
Exclude specific linters, running all others
|
||||||
|
|
||||||
|
As a pre-commit hook:
|
||||||
As a pre-commit hook
|
---------------------
|
||||||
--------------------
|
|
||||||
|
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import git_lint
|
import git_lint
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
#!/usr/bin/env hy
|
||||||
|
(import ConfigParser os subprocess operator re gettext sys getopt)
|
||||||
|
(def _ gettext.gettext)
|
||||||
|
(def *version* "0.0.2")
|
||||||
|
|
||||||
|
(defn tap [a] (print "TAP:" a) a)
|
||||||
|
|
||||||
|
(def optlist [["o" "only" true (_ "A comma-separated list of only those linters to run") ["x"]]
|
||||||
|
["x" "exclude" true (_ "A comma-separated list of linters to skip") []]
|
||||||
|
["l" "linters" false (_ "Show the list of configured linters")]
|
||||||
|
["b" "base" false (_ "Check all changed files in the repository, not just those in the current directory.") []]
|
||||||
|
["a" "all" false (_ "Scan all files in the repository, not just those that have changed.")]
|
||||||
|
["e" "every" false (_ "Short for -b -a, scan everything")]
|
||||||
|
["w" "workspace" false (_ "Scan the workspace") ["s"]]
|
||||||
|
["s" "staging" false (_ "Scan the staging area (pre-commit).") []]
|
||||||
|
["g" "changes" false (_ "Report lint failures only for diff'd sections") ["l"]]
|
||||||
|
["m" "complete" false (_ "Report lint failures for all files") []]
|
||||||
|
["c" "config" true (_ "Path to config file") []]
|
||||||
|
["h" "help" false (_ "This help message") []]
|
||||||
|
["v" "version" false (_"Version information") []]])
|
||||||
|
|
||||||
|
; Given a set of command-line arguments, compare that to a mapped
|
||||||
|
; version of the optlist and return a canonicalized dictionary of all
|
||||||
|
; the arguments that have been set. For example "-c" and "--config"
|
||||||
|
; will both be mapped to "config".
|
||||||
|
|
||||||
|
; Given a prefix of one or two dashes and a position in the above
|
||||||
|
; array, creates a function to map either the short or long option
|
||||||
|
; to the option name.
|
||||||
|
|
||||||
|
(defn make-opt-assoc [prefix pos]
|
||||||
|
(fn [acc it] (assoc acc (+ prefix (get it pos)) (get it 1)) acc))
|
||||||
|
|
||||||
|
; Using the above, create a full map of all arguments, then return a
|
||||||
|
; function ready to look up any argument and return the option name.
|
||||||
|
|
||||||
|
(defn make-options-rationalizer [optlist]
|
||||||
|
(let [
|
||||||
|
[short-opt-assoc (make-opt-assoc "-" 0)]
|
||||||
|
[long-opt-assoc (make-opt-assoc "--" 1)]
|
||||||
|
[fullset
|
||||||
|
(reduce (fn [acc i] (-> (short-opt-assoc acc i)
|
||||||
|
(long-opt-assoc i))) optlist {})]]
|
||||||
|
(fn [acc it] (do (assoc acc (get fullset (get it 0)) (get it 1)) acc))))
|
||||||
|
|
||||||
|
(defn print-version []
|
||||||
|
(print (.format "git-lint (hy version {})" *version*))
|
||||||
|
(print "Copyright (c) 2008, 2016 Kenneth M. \"Elf\" Sternberg <elf.sternberg@gmail.com>")
|
||||||
|
(sys.exit))
|
||||||
|
|
||||||
|
(defn print-help []
|
||||||
|
(print "Usage: git lint [options] [filename]")
|
||||||
|
(for [item optlist] (print (.format " -{:<1} --{:<12} {}" (get item 0) (get item 1) (get item 3))))
|
||||||
|
(sys.exit))
|
||||||
|
|
||||||
|
(defn get-git-response [cmd]
|
||||||
|
(let [[fullcmd (+ ["git"] cmd)]
|
||||||
|
[process (subprocess.Popen fullcmd
|
||||||
|
:stdout subprocess.PIPE
|
||||||
|
:stderr subprocess.PIPE)]
|
||||||
|
[(, out err) (.communicate process)]]
|
||||||
|
(, out err process.returncode)))
|
||||||
|
|
||||||
|
(defn run-git-command [cmd]
|
||||||
|
(let [[fullcmd (+ ["git"] cmd)]]
|
||||||
|
(subprocess.call fullcmd
|
||||||
|
:stdout subprocess.PIPE
|
||||||
|
:stderr subprocess.PIPE)))
|
||||||
|
|
||||||
|
(defn get-shell-response [fullcmd]
|
||||||
|
(let [[process (subprocess.Popen fullcmd
|
||||||
|
:stdout subprocess.PIPE
|
||||||
|
:stderr subprocess.PIPE
|
||||||
|
:shell True)]
|
||||||
|
[(, out err) (.communicate process)]]
|
||||||
|
(, out err process.returncode)))
|
||||||
|
|
||||||
|
(def git-base (let [[(, out error returncode)
|
||||||
|
(get-git-response ["rev-parse" "--show-toplevel"])]]
|
||||||
|
(if (not (= returncode 0)) None (.rstrip out))))
|
||||||
|
|
||||||
|
(defn find-config-file [options]
|
||||||
|
(if (.has_key options "config")
|
||||||
|
(let [[config (get options "config")]
|
||||||
|
[configpath (os.path.abspath config)]]
|
||||||
|
(if (os.path.isfile configpath)
|
||||||
|
configpath
|
||||||
|
(sys.exit (.format (_ "Configuration file not found: {}\n") config))))
|
||||||
|
(let [[home (os.path.join (.get os.environ "HOME"))]
|
||||||
|
[possibles (, (os.path.join git-base ".git-lint")
|
||||||
|
(os.path.join git-base ".git-lint/config")
|
||||||
|
(os.path.join home ".git-lint")
|
||||||
|
(os.path.join home ".git-lint/config"))]
|
||||||
|
[matches (list (filter os.path.isfile possibles))]]
|
||||||
|
(if (len matches) (get matches 0) (sys.exit (_ "No configuration file found"))))))
|
||||||
|
|
||||||
|
(defn load-config-file [path]
|
||||||
|
(let [[configloader (.SafeConfigParser ConfigParser)]
|
||||||
|
[config {}]]
|
||||||
|
(.read configloader path)
|
||||||
|
(.set configloader "DEFAULT" "repdir" git-base)
|
||||||
|
(for [section (.sections configloader)]
|
||||||
|
(let [[pairs {}]]
|
||||||
|
(for [(, k v) (.items configloader section)]
|
||||||
|
(assoc pairs k v))
|
||||||
|
(assoc config section pairs)))
|
||||||
|
config))
|
||||||
|
|
||||||
|
(defn make-match-filter-matcher [extensions]
|
||||||
|
(->> (map (fn [s] (.split s ",")) extensions)
|
||||||
|
(reduce operator.add)
|
||||||
|
(map (fn [s] (.strip s)))
|
||||||
|
(set)
|
||||||
|
(filter (fn [s] (not (= 0 (len s)))))
|
||||||
|
(map (fn [s] (.sub re "^\." "" s)))
|
||||||
|
(.join "|")
|
||||||
|
((fn [s] (+ "\.(" s ")$")))
|
||||||
|
((fn [s] (re.compile s re.I)))))
|
||||||
|
|
||||||
|
(defn make-match-filter [config]
|
||||||
|
(let [[matcher (make-match-filter-matcher (map (fn [v] (.get v "match" "" ))
|
||||||
|
(.itervalues config)))]]
|
||||||
|
(print matcher)
|
||||||
|
(fn [path] (.search matcher path))))
|
||||||
|
|
||||||
|
(defn print-linters [config]
|
||||||
|
(print (_ "Currently supported linters:"))
|
||||||
|
(for [(, linter items) (.iteritems config)]
|
||||||
|
(print (.format "{:<14} {}" linter (.get items "comment" "")))))
|
||||||
|
|
||||||
|
(defn git-lint-main [options]
|
||||||
|
(print git-base)
|
||||||
|
(print (os.path.abspath __file__))
|
||||||
|
(let [[config (load-config-file (find-config-file))]]
|
||||||
|
(print options)
|
||||||
|
(print config)
|
||||||
|
(print (make-match-filter config))))
|
||||||
|
|
||||||
|
(defmain [&rest args]
|
||||||
|
(try
|
||||||
|
(let [[optstringsshort
|
||||||
|
(.join "" (map (fn [i] (+ (. i [0]) (cond [(. i [2]) ":"] [true ""]))) optlist))]
|
||||||
|
[optstringslong
|
||||||
|
(list (map (fn [i] (+ (. i [1]) (cond [(. i [2]) "="] [true ""]))) optlist))]
|
||||||
|
[(, opt arg)
|
||||||
|
(getopt.getopt (slice args 1) optstringsshort optstringslong)]
|
||||||
|
[rationalize-options
|
||||||
|
(make-options-rationalizer optlist)]
|
||||||
|
[options (reduce (fn [acc i] (rationalize-options acc i)) opt {})]
|
||||||
|
[config (load-config-file (find-config-file options))]]
|
||||||
|
(cond [(.has_key options "help") (print-help)]
|
||||||
|
[(.has_key options "version") (print-version)]
|
||||||
|
[(.has_key options "linters") (print-linters config)]
|
||||||
|
[true (git-lint-main options)]))
|
||||||
|
(catch [err getopt.GetoptError]
|
||||||
|
(print (str err))
|
||||||
|
(print-help))))
|
Loading…
Reference in New Issue