88from pathlib import PosixPath
99
1010from dacite import from_dict
11+ import dacite
1112
1213from .sync_plan import LogicalSyncPlan
1314from .utils import coalesce , path_matches_patterns
1415
1516CONFIG_NAME = "dot.conf.json"
1617CONFIG_PATH = os .getenv ("DOTTER_CONFIG_ROOT" , "~/.config/dotter" )
17- CONFIG_DEFAULT = {
18+
19+ CONFIG_STANDARD = {
1820 "defaults" : {
1921 "root" : "~/" ,
2022
2830 "copy" : ".xcopy"
2931 },
3032 "ignore" : [
31- "*/.DS_Store" ,
32- "*/*.bak" ,
33- "*/.gitkeep" ,
34- "*/.idea/*" ,
35- "*/__pycache__/*"
33+ "*/.*" ,
34+ "*/.*/*" ,
3635 ]
3736 },
3837}
3938
39+ CONFIG_STANDARD_DEFAULTS = CONFIG_STANDARD .get ("defaults" )
40+
4041LINK_MODE_RLINK = "recursive_link"
41- LINK_MODE_LINK = "link"
42+ LINK_MODE_LINK = "link"
4243LINK_MODE_RCOPY = "recursive_copy"
43- LINK_MODE_COPY = "copy"
44+ LINK_MODE_COPY = "copy"
4445LINK_MODE_TOUCH = "touch"
4546
4647ConfigLinkMode = Union [
@@ -66,6 +67,8 @@ def __post_init__(self):
6667 self .root = PosixPath (self .root ).expanduser ().resolve ()
6768
6869 def merge (self , override ) -> ConfigPatternSetting :
70+ if override is None :
71+ return self
6972 return ConfigPatternSetting (
7073 root = coalesce (override .root , self .root ),
7174 add_dot = coalesce (override .add_dot , self .add_dot ),
@@ -84,6 +87,14 @@ class ConfigCategory:
8487
8588 _root : PosixPath = None
8689
90+ def __post_init__ (self ):
91+ if self .defaults is None :
92+ self .defaults = ConfigPatternSetting ()
93+ if self .topics is None :
94+ self .topics = {}
95+ if self .disabled is None :
96+ self .disabled = []
97+
8798 @property
8899 def root (self ):
89100 return self ._root
@@ -92,7 +103,11 @@ def root(self):
92103 def root (self , path : PosixPath ):
93104 self ._root = path
94105
95- def merge_overrides (self ):
106+ def merge_defaults (self ):
107+ defaults = from_dict (ConfigPatternSetting , CONFIG_STANDARD_DEFAULTS )
108+ self .defaults = defaults .merge (self .defaults )
109+
110+ def merge_topics (self ):
96111 for topic , override in self .topics .items ():
97112 self .topics [topic ] = self .defaults .merge (override )
98113
@@ -133,12 +148,13 @@ def load(category: str = None) -> Optional[Config]:
133148 d = json .load (conf_fd )
134149 config_data = from_dict (ConfigCategory , d )
135150 except FileNotFoundError :
136- config_data = from_dict ( ConfigCategory , CONFIG_DEFAULT )
151+ config_data = ConfigCategory ( )
137152
138153 if config_data is None :
139154 return
140155
141156 config_data .root = config_category_path
157+ config_data .merge_defaults ()
142158
143159 for contents in config_category_path .iterdir ():
144160 if not contents .is_dir ():
@@ -148,7 +164,7 @@ def load(category: str = None) -> Optional[Config]:
148164 if contents .name not in config_data .topics :
149165 config_data .topics [contents .name ] = ConfigPatternSetting ()
150166
151- config_data .merge_overrides ()
167+ config_data .merge_topics ()
152168
153169 conf = Config (
154170 config_root = config_root_path ,
@@ -195,15 +211,19 @@ def compute_topic_operations(link_items: List[PosixPath], link_config: ConfigPat
195211
196212 seen_prefixes : set [str ] = set ()
197213 for link_path in link_paths :
198- op_type , src_path , dst_path = _determine_operation (
214+ op_type_switch , src_path , dst_path = _determine_operation (
199215 link_config , link_item .parent , link_path ,
200216 )
217+
201218 if str (src_path ) in seen_prefixes :
202219 continue
220+ if src_path .is_dir () and op_type == op_type_switch :
221+ continue
222+
203223 seen_prefixes .add (str (src_path ))
204224
205225 topic_ops .append (LogicalSyncPlan (
206- type = op_type ,
226+ type = op_type_switch ,
207227 src_path = src_path ,
208228 dst_path = dst_path ,
209229 ))
@@ -244,7 +264,7 @@ def _rename_path(path: PosixPath, base_path: PosixPath, new_base_path: PosixPath
244264 return new_base_path .joinpath (rel_path )
245265
246266
247- def _split_by_modifiers (path : str , modifiers : dict [str , str ]) -> Optional [(str , str , str , str )]:
267+ def _split_by_modifiers (path : str , modifiers : Dict [str , str ]) -> Optional [(str , str , str , str )]:
248268 (rext , prefix_path , src_path , suffix ) = (None , path , path , "" )
249269 for ext_name , ext in modifiers .items ():
250270 idx = path .find (ext )
0 commit comments