| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent a1e2f63 commit 4d36f8f
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -271,9 +271,9 @@ def read(self): | |||
| 271 | 271 | if not hasattr(file_object, "seek"): | |
| 272 | 272 | try: | |
| 273 | 273 | fp = open(file_object) | |
| 274 | + close_fp = True | ||
| 274 | 275 | except IOError,e: | |
| 275 | 276 | continue | |
| 276 | - close_fp = True | ||
| 277 | 277 | # END fp handling | |
| 278 | 278 | ||
| 279 | 279 | try: | |
@@ -308,17 +308,21 @@ def write(self): | |||
| 308 | 308 | :raise IOError: if this is a read-only writer instance or if we could not obtain | |
| 309 | 309 | a file lock""" | |
| 310 | 310 | self._assure_writable("write") | |
| 311 | - self._lock._obtain_lock() | ||
| 312 | - | ||
| 313 | 311 | ||
| 314 | 312 | fp = self._file_or_files | |
| 315 | 313 | close_fp = False | |
| 316 | 314 | ||
| 315 | + # we have a physical file on disk, so get a lock | ||
| 316 | + if isinstance(fp, (basestring, file)): | ||
| 317 | + self._lock._obtain_lock() | ||
| 318 | + # END get lock for physical files | ||
| 319 | + | ||
| 317 | 320 | if not hasattr(fp, "seek"): | |
| 318 | 321 | fp = open(self._file_or_files, "w") | |
| 319 | 322 | close_fp = True | |
| 320 | 323 | else: | |
| 321 | 324 | fp.seek(0) | |
| 325 | + # END handle stream or file | ||
| 322 | 326 | ||
| 323 | 327 | # WRITE DATA | |
| 324 | 328 | try: | |
@@ -390,7 +394,7 @@ def get_value(self, section, option, default = None): | |||
| 390 | 394 | return valuestr | |
| 391 | 395 | ||
| 392 | 396 | @needs_values | |
| 393 | - @set_dirty_and_flush_changes | ||
| 397 | + @set_dirty_and_flush_changes | ||
| 394 | 398 | def set_value(self, section, option, value): | |
| 395 | 399 | """Sets the given option in section to the given value. | |
| 396 | 400 | It will create the section if required, and will not throw as opposed to the default | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,6 +6,13 @@ | |||
| 6 | 6 | ||
| 7 | 7 | __all__ = ("Submodule", ) | |
| 8 | 8 | ||
| 9 | + class SubmoduleConfigParser(GitConfigParser): | ||
| 10 | + """Catches calls to _write, and updates the .gitmodules blob in the index | ||
| 11 | + with the new data, if we have written into a stream. Otherwise it will | ||
| 12 | + add the local file to the index to make it correspond with the working tree.""" | ||
| 13 | + _mutating_methods_ = tuple() | ||
| 14 | + | ||
| 15 | + | ||
| 9 | 16 | class Submodule(base.IndexObject): | |
| 10 | 17 | """Implements access to a git submodule. They are special in that their sha | |
| 11 | 18 | represents a commit in the submodule's repository which is to be checked out | |
@@ -20,14 +27,14 @@ class Submodule(base.IndexObject): | |||
| 20 | 27 | # this is a bogus type for base class compatability | |
| 21 | 28 | type = 'submodule' | |
| 22 | 29 | ||
| 23 | - __slots__ = ('_root_tree', '_url', '_ref') | ||
| 30 | + __slots__ = ('_parent_commit', '_url', '_ref') | ||
| 24 | 31 | ||
| 25 | 32 | def _set_cache_(self, attr): | |
| 26 | 33 | if attr == 'size': | |
| 27 | 34 | raise ValueError("Submodules do not have a size as they do not refer to anything in this repository") | |
| 28 | - elif attr == '_root_tree': | ||
| 35 | + elif attr == '_parent_commit': | ||
| 29 | 36 | # set a default value, which is the root tree of the current head | |
| 30 | - self._root_tree = self.repo.tree() | ||
| 37 | + self._parent_commit = self.repo.commit() | ||
| 31 | 38 | elif attr in ('path', '_url', '_ref'): | |
| 32 | 39 | reader = self.config_reader() | |
| 33 | 40 | # default submodule values | |
@@ -39,13 +46,26 @@ def _set_cache_(self, attr): | |||
| 39 | 46 | super(Submodule, self)._set_cache_(attr) | |
| 40 | 47 | # END handle attribute name | |
| 41 | 48 | ||
| 42 | - def _fp_config(self): | ||
| 49 | + def _sio_modules(self): | ||
| 43 | 50 | """:return: Configuration file as StringIO - we only access it through the respective blob's data""" | |
| 44 | - return StringIO(self._root_tree[self.kModulesFile].datastream.read()) | ||
| 51 | + sio = StringIO(self._parent_commit.tree[self.kModulesFile].datastream.read()) | ||
| 52 | + sio.name = self.kModulesFile | ||
| 53 | + return sio | ||
| 45 | 54 | ||
| 46 | 55 | def _config_parser(self, read_only): | |
| 47 | 56 | """:return: Config Parser constrained to our submodule in read or write mode""" | |
| 48 | - parser = GitConfigParser(self._fp_config(), read_only = read_only) | ||
| 57 | + parent_matches_head = self.repo.head.commit == self._parent_commit | ||
| 58 | + if not self.repo.bare and parent_matches_head: | ||
| 59 | + fp_module = self.kModulesFile | ||
| 60 | + else: | ||
| 61 | + fp_module = self._sio_modules() | ||
| 62 | + # END handle non-bare working tree | ||
| 63 | + | ||
| 64 | + if not read_only and not parent_matches_head: | ||
| 65 | + raise ValueError("Cannot write blobs of 'historical' submodule configurations") | ||
| 66 | + # END handle writes of historical submodules | ||
| 67 | + | ||
| 68 | + parser = GitConfigParser(fp_module, read_only = read_only) | ||
| 49 | 69 | return SectionConstraint(parser, 'submodule "%s"' % self.path) | |
| 50 | 70 | ||
| 51 | 71 | #{ Edit Interface | |
@@ -61,21 +81,24 @@ def add(cls, repo, path, url, skip_init=False): | |||
| 61 | 81 | :param skip_init: if True, the new repository will not be cloned to its location. | |
| 62 | 82 | :return: The newly created submodule instance""" | |
| 63 | 83 | ||
| 64 | - def set_root_tree(self, root_tree): | ||
| 65 | - """Set this instance to use the given tree which is supposed to contain the | ||
| 66 | - .gitmodules blob. | ||
| 67 | - :param root_tree: Tree'ish reference pointing at the root_tree | ||
| 68 | - :raise ValueError: if the root_tree didn't contain the .gitmodules blob.""" | ||
| 69 | - tree = self.repo.tree(root_tree) | ||
| 70 | - if self.kModulesFile not in tree: | ||
| 71 | - raise ValueError("Tree %s did not contain the %s file" % (root_tree, self.kModulesFile)) | ||
| 84 | + def set_parent_commit(self, commit): | ||
| 85 | + """Set this instance to use the given commit whose tree is supposed to | ||
| 86 | + contain the .gitmodules blob. | ||
| 87 | + :param commit: Commit'ish reference pointing at the root_tree | ||
| 88 | + :raise ValueError: if the commit's tree didn't contain the .gitmodules blob.""" | ||
| 89 | + pcommit = self.repo.commit(commit) | ||
| 90 | + if self.kModulesFile not in pcommit.tree: | ||
| 91 | + raise ValueError("Tree of commit %s did not contain the %s file" % (commit, self.kModulesFile)) | ||
| 72 | 92 | # END handle exceptions | |
| 73 | - self._root_tree = tree | ||
| 93 | + self._parent_commit = pcommit | ||
| 74 | 94 | ||
| 75 | - # clear the possibly changing values | ||
| 76 | - del(self.path) | ||
| 77 | - del(self._ref) | ||
| 78 | - del(self._url) | ||
| 95 | + # clear the possibly changed values | ||
| 96 | + for name in ('path', '_ref', '_url'): | ||
| 97 | + try: | ||
| 98 | + delattr(self, name) | ||
| 99 | + except AttributeError: | ||
| 100 | + pass | ||
| 101 | + # END for each name to delete | ||
| 79 | 102 | ||
| 80 | 103 | def config_writer(self): | |
| 81 | 104 | """:return: a config writer instance allowing you to read and write the data | |
@@ -108,11 +131,10 @@ def url(self): | |||
| 108 | 131 | """:return: The url to the repository which our module-repository refers to""" | |
| 109 | 132 | return self._url | |
| 110 | 133 | ||
| 111 | - def root_tree(self): | ||
| 112 | - """:return: Tree instance referring to the tree which contains the .gitmodules file | ||
| 113 | - we are to use | ||
| 114 | - :note: will always point to the current head's root tree if it was not set explicitly""" | ||
| 115 | - return self._root_tree | ||
| 134 | + def parent_commit(self): | ||
| 135 | + """:return: Commit instance with the tree containing the .gitmodules file | ||
| 136 | + :note: will always point to the current head's commit if it was not set explicitly""" | ||
| 137 | + return self._parent_commit | ||
| 116 | 138 | ||
| 117 | 139 | def config_reader(self): | |
| 118 | 140 | """:return: ConfigReader instance which allows you to qurey the configuration values | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,9 +14,7 @@ class TestBase(TestCase): | |||
| 14 | 14 | ||
| 15 | 15 | def _to_memcache(self, file_path): | |
| 16 | 16 | fp = open(file_path, "r") | |
| 17 | - sio = StringIO.StringIO() | ||
| 18 | - sio.write(fp.read()) | ||
| 19 | - sio.seek(0) | ||
| 17 | + sio = StringIO.StringIO(fp.read()) | ||
| 20 | 18 | sio.name = file_path | |
| 21 | 19 | return sio | |
| 22 | 20 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -19,7 +19,9 @@ def _do_base_tests(self, rwrepo): | |||
| 19 | 19 | # size is invalid | |
| 20 | 20 | self.failUnlessRaises(ValueError, getattr, sm, 'size') | |
| 21 | 21 | ||
| 22 | - # fails if tree has no gitmodule file | ||
| 22 | + # set_parent_commit fails if tree has no gitmodule file | ||
| 23 | + | ||
| 24 | + | ||
| 23 | 25 | ||
| 24 | 26 | if rwrepo.bare: | |
| 25 | 27 | # module fails | |
@@ -28,6 +30,8 @@ def _do_base_tests(self, rwrepo): | |||
| 28 | 30 | # get the module repository | |
| 29 | 31 | pass | |
| 30 | 32 | # END bare handling | |
| 33 | + | ||
| 34 | + # Writing of historical submodule configurations must not work | ||
| 31 | 35 | ||
| 32 | 36 | @with_rw_repo(kCOTag) | |
| 33 | 37 | def test_base_rw(self, rwrepo): | |
| Back | FazBrowse Home | New Git URL |
0 commit comments