Umożliwianie ustawiania opisu zmian oraz nazwy użytkownika w unicode (utf-8).
[redakcja.git] / lib / hg.py
1 # -*- coding: utf-8 -*-
2 import os
3 import codecs
4 from mercurial import localrepo, ui, error, match, node, encoding
5
6
7 encoding.encoding = 'utf-8'
8
9
10 class RepositoryDoesNotExist(Exception):
11     pass
12
13
14 class Repository(object):
15     """Abstrakcja repozytorium Mercurial. Działa z Mercurial w wersji 1.3.1."""
16     
17     def __init__(self, path, create=False):
18         self.ui = ui.ui()
19         self.ui.config('ui', 'quiet', 'true')
20         self.ui.config('ui', 'interactive', 'false')
21         
22         self.real_path = os.path.realpath(path)
23         self.repo = self.open_repository(self.real_path, create)
24         self._pending_files = []
25     
26     def open_repository(self, path, create=False):
27         if os.path.isdir(path):
28             try:
29                 return localrepo.localrepository(self.ui, path)
30             except error.RepoError:
31                 # dir is not an hg repo, we must init it
32                 if create:
33                     return localrepo.localrepository(self.ui, path, create=1)
34         elif create:
35             os.makedirs(path)
36             return localrepo.localrepository(self.ui, path, create=1)
37         raise RepositoryDoesNotExist("Repository %s does not exist." % path)
38         
39     def all_files(self):
40         return list(self.repo['tip'])
41     
42     def get_file(self, path):
43         ctx = self.repo.changectx(None)
44         return ctx.filectx(path)
45     
46     def add_file(self, path, value):
47         f = codecs.open(os.path.join(self.real_path, path), 'w', encoding='utf-8')
48         f.write(value)
49         f.close()
50
51         if path not in self._pending_files:
52             self._pending_files.append(path)
53     
54     def commit(self, message=u'hgshelve auto commit', key=None, user=None):
55         """
56         Commit unsynchronized data to disk.
57         Arguments::
58
59          - message: mercurial's changeset message
60          - key: supply to sync only one key
61         """
62         if isinstance(message, unicode):
63             message = message.encode('utf-8')
64         if isinstance(user, unicode):
65             user = user.encode('utf-8')
66         
67         commited = False
68         rev = None
69         files_to_add = []
70         files_to_remove = []
71         files_to_commit = []
72
73         # first of all, add absent data and clean removed
74         if key is None:
75             # will commit all keys
76             pending_files = self._pending_files
77         else:
78             if key not in self._pending_files:
79                 # key isn't changed
80                 return None
81             else:
82                 pending_files = [key]
83         for path in pending_files:
84             files_to_commit.append(path)
85             if path in self.all_files():
86                 if not os.path.exists(os.path.join(self.real_path, path)):
87                     # file removed
88                     files_to_remove.append(path)
89             else:
90                 # file added
91                 files_to_add.append(path)
92         # hg add
93         if files_to_add:
94             self.repo.add(files_to_add)
95         # hg forget
96         if files_to_remove:
97             self.repo.forget(files_to_remove)
98         # ---- hg commit
99         if files_to_commit:
100             matcher = match.match(self.repo.root, self.repo.root, files_to_commit, default='path')
101             rev = self.repo.commit(message, user=user, match=matcher)
102             commited = True
103         # clean pending keys
104         for key in pending_files:
105             self._pending_files.remove(key)
106         # if commited:
107             # reread keys
108             # self._keys = self.get_persisted_objects_keys()
109             # return node.hex(rev)
110