2020defenc ,
2121force_text ,
2222with_metaclass ,
23- PY3
23+ PY3 ,
24+ is_win ,
2425)
2526from git .util import LockFile
2627
4041log = logging .getLogger ('git.config' )
4142log .addHandler (logging .NullHandler ())
4243
44+ # invariants
45+ # represents the configuration level of a configuration file
46+ CONFIG_LEVELS = ("system" ,"user" ,"global" ,"repository" )
47+
4348
4449class MetaParserBuilder (abc .ABCMeta ):
4550
@@ -191,6 +196,26 @@ def items_all(self):
191196return [(k ,self .getall (k ))for k in self ]
192197
193198
199+ def get_config_path (config_level ):
200+
201+ # we do not support an absolute path of the gitconfig on windows ,
202+ # use the global config instead
203+ if is_win and config_level == "system" :
204+ config_level = "global"
205+
206+ if config_level == "system" :
207+ return "/etc/gitconfig"
208+ elif config_level == "user" :
209+ config_home = os .environ .get ("XDG_CONFIG_HOME" )or osp .join (os .environ .get ("HOME" ,'~' ),".config" )
210+ return osp .normpath (osp .expanduser (osp .join (config_home ,"git" ,"config" )))
211+ elif config_level == "global" :
212+ return osp .normpath (osp .expanduser ("~/.gitconfig" ))
213+ elif config_level == "repository" :
214+ raise ValueError ("repository configuration level not allowed" )
215+
216+ ValueError ("Invalid configuration level: %r" % config_level )
217+
218+
194219class GitConfigParser (with_metaclass (MetaParserBuilder ,cp .RawConfigParser ,object )):
195220
196221"""Implements specifics required to read git style configuration files.
@@ -229,7 +254,7 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, obje
229254# list of RawConfigParser methods able to change the instance
230255_mutating_methods_ = ("add_section" ,"remove_section" ,"remove_option" ,"set" )
231256
232- def __init__ (self ,file_or_files ,read_only = True ,merge_includes = True ):
257+ def __init__ (self ,file_or_files = None ,read_only = True ,merge_includes = True , config_level = None ):
233258"""Initialize a configuration reader to read the given file_or_files and to
234259 possibly allow changes to it by setting read_only False
235260
@@ -251,7 +276,17 @@ def __init__(self, file_or_files, read_only=True, merge_includes=True):
251276if not hasattr (self ,'_proxies' ):
252277self ._proxies = self ._dict ()
253278
254- self ._file_or_files = file_or_files
279+ if file_or_files is not None :
280+ self ._file_or_files = file_or_files
281+ else :
282+ if config_level is None :
283+ if read_only :
284+ self ._file_or_files = [get_config_path (f )for f in CONFIG_LEVELS [:- 1 ]]
285+ else :
286+ raise ValueError ("No configuration level or configuration files specified" )
287+ else :
288+ self ._file_or_files = [get_config_path (config_level )]
289+
255290self ._read_only = read_only
256291self ._dirty = False
257292self ._is_initialized = False