1 """Save settings, bookmarks, etc.
3 from __future__
import division
, absolute_import
, unicode_literals
10 from . import resources
14 """Transform None and non-dicts into dicts"""
15 if isinstance(obj
, dict):
23 """Transform None and non-lists into lists"""
24 if isinstance(obj
, list):
26 elif isinstance(obj
, tuple):
35 with core
.xopen(path
, 'rt') as fp
:
36 return mkdict(json
.load(fp
))
37 except (ValueError, TypeError, OSError, IOError): # bad path or json
41 def write_json(values
, path
):
43 parent
= os
.path
.dirname(path
)
44 if not core
.isdir(parent
):
46 with core
.xopen(path
, 'wt') as fp
:
47 json
.dump(values
, fp
, indent
=4)
48 except (ValueError, TypeError, OSError, IOError):
49 sys
.stderr
.write('git-cola: error writing "%s"\n' % path
)
52 class Settings(object):
53 config_path
= resources
.config_home('settings')
54 bookmarks
= property(lambda self
: mklist(self
.values
['bookmarks']))
55 gui_state
= property(lambda self
: mkdict(self
.values
['gui_state']))
56 recent
= property(lambda self
: mklist(self
.values
['recent']))
57 copy_formats
= property(lambda self
: mklist(self
.values
['copy_formats']))
59 def __init__(self
, verify
=git
.is_git_worktree
):
60 """Load existing settings if they exist"""
69 def remove_missing(self
):
70 missing_bookmarks
= []
73 for bookmark
in self
.bookmarks
:
74 if not self
.verify(bookmark
['path']):
75 missing_bookmarks
.append(bookmark
)
77 for bookmark
in missing_bookmarks
:
79 self
.bookmarks
.remove(bookmark
)
83 for recent
in self
.recent
:
84 if not self
.verify(recent
['path']):
85 missing_recent
.append(recent
)
87 for recent
in missing_recent
:
89 self
.recent
.remove(recent
)
93 def add_bookmark(self
, path
, name
):
94 """Adds a bookmark to the saved settings"""
95 bookmark
= {'path': path
, 'name': name
}
96 if bookmark
not in self
.bookmarks
:
97 self
.bookmarks
.append(bookmark
)
99 def remove_bookmark(self
, path
, name
):
100 """Remove a bookmark"""
101 bookmark
= {'path': path
, 'name': name
}
103 self
.bookmarks
.remove(bookmark
)
107 def rename_bookmark(self
, path
, name
, new_name
):
108 return rename_entry(self
.bookmarks
, path
, name
, new_name
)
110 def add_recent(self
, path
, max_recent
):
112 index
= [recent
['path'] for recent
in self
.recent
].index(path
)
113 entry
= self
.recent
.pop(index
)
114 except (IndexError, ValueError):
116 'name': os
.path
.basename(path
),
119 self
.recent
.insert(0, entry
)
120 if len(self
.recent
) >= max_recent
:
123 def remove_recent(self
, path
):
124 """Removes an item from the recent items list"""
127 recent
.get('path', '') for recent
in self
.recent
132 self
.recent
.pop(index
)
136 def rename_recent(self
, path
, name
, new_name
):
137 return rename_entry(self
.recent
, path
, name
, new_name
)
140 return self
.config_path
143 write_json(self
.values
, self
.path())
146 self
.values
.update(self
.asdict())
147 self
.upgrade_settings()
148 self
.remove_missing()
150 def upgrade_settings(self
):
151 """Upgrade git-cola settings"""
152 # Upgrade bookmarks to the new dict-based bookmarks format.
153 if self
.bookmarks
and not isinstance(self
.bookmarks
[0], dict):
154 bookmarks
= [dict(name
=os
.path
.basename(path
), path
=path
)
155 for path
in self
.bookmarks
]
156 self
.values
['bookmarks'] = bookmarks
158 if self
.recent
and not isinstance(self
.recent
[0], dict):
159 recent
= [dict(name
=os
.path
.basename(path
), path
=path
)
160 for path
in self
.recent
]
161 self
.values
['recent'] = recent
165 if core
.exists(path
):
166 return read_json(path
)
167 # We couldn't find ~/.config/git-cola, try ~/.cola
169 path
= os
.path
.join(core
.expanduser('~'), '.cola')
170 if core
.exists(path
):
171 json_values
= read_json(path
)
172 # Keep only the entries we care about
173 for key
in self
.values
:
175 values
[key
] = json_values
[key
]
180 def reload_recent(self
):
181 values
= self
.asdict()
182 self
.values
['recent'] = mklist(values
.get('recent', []))
184 def save_gui_state(self
, gui
):
185 """Saves settings for a cola view"""
187 self
.gui_state
[name
] = mkdict(gui
.export_state())
190 def get_gui_state(self
, gui
):
191 """Returns the saved state for a gui"""
193 state
= mkdict(self
.gui_state
[gui
.name()])
195 state
= self
.gui_state
[gui
.name()] = {}
199 def rename_entry(entries
, path
, name
, new_name
):
200 entry
= {'name': name
, 'path': path
}
202 index
= entries
.index(entry
)
206 if all([item
['name'] != new_name
for item
in entries
]):
207 entries
[index
]['name'] = new_name
213 class Session(Settings
):
214 """Store per-session settings"""
216 _sessions_dir
= resources
.config_home('sessions')
218 repo
= property(lambda self
: self
.values
['repo'])
220 def __init__(self
, session_id
, repo
=None):
221 Settings
.__init
__(self
)
222 self
.session_id
= session_id
223 self
.values
.update({'repo': repo
})
226 return os
.path
.join(self
._sessions
_dir
, self
.session_id
)
230 if core
.exists(path
):
231 self
.values
.update(read_json(path
))
234 except (OSError, ValueError):