import { red } from 'chalk' ; import { readdirSync , readFileSync , statSync } from 'fs' ; import { task } from 'gulp' ; import { IMinimatch , Minimatch } from 'minimatch' ; import { join } from 'path' ; import { execNodeTask } from '../util/task-helpers' ; /** Glob that matches all SCSS or CSS files that should be linted. */ const styleGlob = 'src/**/*.+(css|scss)' ; /** List of flags that will passed to the different TSLint tasks. */ const tsLintBaseFlags = [ '-c' , 'tslint.json' , '--project' , './tsconfig.json' ] ; /** Path for the Github owners file. */ const ownersFilePath = '.github/CODEOWNERS' ; /** Path for the .gitignore file. */ const gitIgnorePath = '.gitignore' ; task ( 'lint' , [ 'tslint' , 'stylelint' , 'ownerslint' ] ) ; /** Task to lint Angular Material's scss stylesheets. */ task ( 'stylelint' , execNodeTask ( 'stylelint' , [ styleGlob , '--config' , 'stylelint-config.json' , '--syntax' , 'scss' ] ) ) ; /** Task to run TSLint against the e2e/ and src/ directories. */ task ( 'tslint' , execNodeTask ( 'tslint' , tsLintBaseFlags ) ) ; /** Task that automatically fixes TSLint warnings. */ task ( 'tslint:fix' , execNodeTask ( 'tslint' , [ ... tsLintBaseFlags , '--fix' ] ) ) ; task ( 'ownerslint' , ( ) => { let errors = 0 ; let ownedPaths = readFileSync ( ownersFilePath , 'utf8' ) . split ( '\n' ) . map ( line => line . trim ( ) ) . filter ( line => line && ! line . startsWith ( '#' ) ) . map ( line => line . split ( /\s+/ ) [ 0 ] ) . map ( path => new Minimatch ( path , { dot : true , matchBase : true } ) ) ; let ignoredPaths = readFileSync ( gitIgnorePath , 'utf8' ) . split ( '\n' ) . map ( line => line . trim ( ) ) . filter ( line => line && ! line . startsWith ( '#' ) ) . map ( path => new Minimatch ( path , { dot : true , matchBase : true } ) ) ; for ( let paths = getChildPaths ( '.' ) ; paths . length ; ) { paths = Array . prototype . concat ( ... paths . filter ( path => ! ignoredPaths . reduce ( ( isIgnored , ignoredPath ) => isIgnored || ignoredPath . match ( '/' + path ) , false ) ) . filter ( path => ! ownedPaths . reduce ( ( isOwned , ownedPath ) => isOwned || isOwnedBy ( path , ownedPath ) , false ) ) . filter ( path => { if ( statSync ( path ) . isFile ( ) ) { console . log ( red ( `No code owner found for "${ path }".` ) ) ; errors ++ ; return false ; } return true ; } ) . map ( path => getChildPaths ( path ) ) ) ; } if ( errors ) { throw Error ( `Found ${ errors } files with no owner.` ) ; } } ) ; /** Check if the given path is owned by the given owned path matcher. */ function isOwnedBy ( path , ownedPath ) { if ( ownedPath . pattern . endsWith ( '**' ) || statSync ( path ) . isFile ( ) ) { return ownedPath . match ( '/' + path ) ; } return false ; } /** Get the immediate child paths of the given path. */ function getChildPaths ( path ) { return readdirSync ( path ) . map ( child => join ( path , child ) ) ; }