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