Home | History | Annotate | Download | only in gitlint
      1 # Copyright 2013-2014 Sebastian Kreft
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #     http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 """Common function used across modules."""
     15 
     16 import io
     17 import os
     18 import re
     19 
     20 
     21 def filter_lines(lines, filter_regex, groups=None):
     22     """Filters out the lines not matching the pattern.
     23 
     24     Args:
     25       lines: list[string]: lines to filter.
     26       pattern: string: regular expression to filter out lines.
     27 
     28     Returns: list[string]: the list of filtered lines.
     29     """
     30     pattern = re.compile(filter_regex)
     31     for line in lines:
     32         match = pattern.search(line)
     33         if match:
     34             if groups is None:
     35                 yield line
     36             elif len(groups) == 1:
     37                 yield match.group(groups[0])
     38             else:
     39                 matched_groups = match.groupdict()
     40                 yield tuple(matched_groups.get(group) for group in groups)
     41 
     42 
     43 # TODO(skreft): add test
     44 def which(program):
     45     """Returns a list of paths where the program is found."""
     46     if (os.path.isabs(program) and os.path.isfile(program) and
     47             os.access(program, os.X_OK)):
     48         return [program]
     49 
     50     candidates = []
     51     locations = os.environ.get("PATH").split(os.pathsep)
     52     for location in locations:
     53         candidate = os.path.join(location, program)
     54         if os.path.isfile(candidate) and os.access(candidate, os.X_OK):
     55             candidates.append(candidate)
     56     return candidates
     57 
     58 
     59 def programs_not_in_path(programs):
     60     """Returns all the programs that are not found in the PATH."""
     61     return [program for program in programs if not which(program)]
     62 
     63 
     64 def _open_for_write(filename):
     65     """Opens filename for writing, creating the directories if needed."""
     66     dirname = os.path.dirname(filename)
     67     if not os.path.exists(dirname):
     68         os.makedirs(dirname)
     69 
     70     return io.open(filename, 'w')
     71 
     72 
     73 def _get_cache_filename(name, filename):
     74     """Returns the cache location for filename and linter name."""
     75     filename = os.path.abspath(filename)[1:]
     76     home_folder = os.path.expanduser('~')
     77     base_cache_dir = os.path.join(home_folder, '.git-lint', 'cache')
     78 
     79     return os.path.join(base_cache_dir, name, filename)
     80 
     81 
     82 def get_output_from_cache(name, filename):
     83     """Returns the output from the cache if still valid.
     84 
     85     It checks that the cache file is defined and that its modification time is
     86     after the modification time of the original file.
     87 
     88     Args:
     89       name: string: name of the linter.
     90       filename: string: path of the filename for which we are retrieving the
     91         output.
     92 
     93     Returns: a string with the output, if it is still valid, or None otherwise.
     94     """
     95     cache_filename = _get_cache_filename(name, filename)
     96     if (os.path.exists(cache_filename) and
     97             os.path.getmtime(filename) < os.path.getmtime(cache_filename)):
     98         with io.open(cache_filename) as f:
     99             return f.read()
    100 
    101     return None
    102 
    103 
    104 def save_output_in_cache(name, filename, output):
    105     """Saves output in the cache location.
    106 
    107     Args:
    108       name: string: name of the linter.
    109       filename: string: path of the filename for which we are saving the output.
    110       output: string: full output (not yet filetered) of the lint command.
    111     """
    112     cache_filename = _get_cache_filename(name, filename)
    113     with _open_for_write(cache_filename) as f:
    114         f.write(output)
    115