Codebase list python-git / 11d7fea
New upstream version 3.1.7 TANIGUCHI Takaki 3 years ago
121 changed file(s) with 162 addition(s) and 17679 deletion(s). Raw diff Collapse all Expand all
4040 -Pratik Anurag <panurag247365 _at_ gmail.com>
4141 -Harmon <harmon.public _at_ gmail.com>
4242 -Liam Beguin <liambeguin _at_ gmail.com>
43 -Ram Rachum <ram _at_ rachum.com>
4344 Portions derived from other open source works and are clearly marked.
00 Metadata-Version: 1.2
11 Name: GitPython
2 Version: 3.1.3
2 Version: 3.1.7
33 Summary: Python Git Library
44 Home-page: https://github.com/gitpython-developers/GitPython
55 Author: Sebastian Thiel, Michael Trier
5858 git/refs/tag.py
5959 git/repo/__init__.py
6060 git/repo/base.py
61 git/repo/fun.py
62 git/test/__init__.py
63 git/test/test_actor.py
64 git/test/test_base.py
65 git/test/test_blob.py
66 git/test/test_commit.py
67 git/test/test_config.py
68 git/test/test_db.py
69 git/test/test_diff.py
70 git/test/test_docs.py
71 git/test/test_exc.py
72 git/test/test_fun.py
73 git/test/test_git.py
74 git/test/test_index.py
75 git/test/test_reflog.py
76 git/test/test_refs.py
77 git/test/test_remote.py
78 git/test/test_repo.py
79 git/test/test_stats.py
80 git/test/test_submodule.py
81 git/test/test_tree.py
82 git/test/test_util.py
83 git/test/fixtures/.gitconfig
84 git/test/fixtures/blame
85 git/test/fixtures/blame_binary
86 git/test/fixtures/blame_complex_revision
87 git/test/fixtures/blame_incremental
88 git/test/fixtures/blame_incremental_2.11.1_plus
89 git/test/fixtures/cat_file.py
90 git/test/fixtures/cat_file_blob
91 git/test/fixtures/cat_file_blob_nl
92 git/test/fixtures/cat_file_blob_size
93 git/test/fixtures/commit_invalid_data
94 git/test/fixtures/commit_with_gpgsig
95 git/test/fixtures/diff_2
96 git/test/fixtures/diff_2f
97 git/test/fixtures/diff_abbrev-40_full-index_M_raw_no-color
98 git/test/fixtures/diff_change_in_type
99 git/test/fixtures/diff_change_in_type_raw
100 git/test/fixtures/diff_copied_mode
101 git/test/fixtures/diff_copied_mode_raw
102 git/test/fixtures/diff_f
103 git/test/fixtures/diff_file_with_spaces
104 git/test/fixtures/diff_i
105 git/test/fixtures/diff_index_patch
106 git/test/fixtures/diff_index_raw
107 git/test/fixtures/diff_initial
108 git/test/fixtures/diff_mode_only
109 git/test/fixtures/diff_new_mode
110 git/test/fixtures/diff_numstat
111 git/test/fixtures/diff_p
112 git/test/fixtures/diff_patch_binary
113 git/test/fixtures/diff_patch_unsafe_paths
114 git/test/fixtures/diff_raw_binary
115 git/test/fixtures/diff_rename
116 git/test/fixtures/diff_rename_raw
117 git/test/fixtures/diff_tree_numstat_root
118 git/test/fixtures/for_each_ref_with_path_component
119 git/test/fixtures/git_config
120 git/test/fixtures/git_config-inc.cfg
121 git/test/fixtures/git_config_global
122 git/test/fixtures/git_config_multiple
123 git/test/fixtures/git_config_with_comments
124 git/test/fixtures/git_config_with_empty_value
125 git/test/fixtures/git_file
126 git/test/fixtures/index
127 git/test/fixtures/index_merge
128 git/test/fixtures/issue-301_stderr
129 git/test/fixtures/ls_tree_a
130 git/test/fixtures/ls_tree_b
131 git/test/fixtures/ls_tree_commit
132 git/test/fixtures/ls_tree_empty
133 git/test/fixtures/reflog_HEAD
134 git/test/fixtures/reflog_invalid_date
135 git/test/fixtures/reflog_invalid_email
136 git/test/fixtures/reflog_invalid_newsha
137 git/test/fixtures/reflog_invalid_oldsha
138 git/test/fixtures/reflog_invalid_sep
139 git/test/fixtures/reflog_master
140 git/test/fixtures/rev_list
141 git/test/fixtures/rev_list_bisect_all
142 git/test/fixtures/rev_list_commit_diffs
143 git/test/fixtures/rev_list_commit_idabbrev
144 git/test/fixtures/rev_list_commit_stats
145 git/test/fixtures/rev_list_count
146 git/test/fixtures/rev_list_delta_a
147 git/test/fixtures/rev_list_delta_b
148 git/test/fixtures/rev_list_single
149 git/test/fixtures/rev_parse
150 git/test/fixtures/show_empty_commit
151 git/test/fixtures/uncommon_branch_prefix_FETCH_HEAD
152 git/test/fixtures/uncommon_branch_prefix_stderr
153 git/test/lib/__init__.py
154 git/test/lib/helper.py
155 git/test/performance/__init__.py
156 git/test/performance/lib.py
157 git/test/performance/test_commit.py
158 git/test/performance/test_odb.py
159 git/test/performance/test_streams.py
61 git/repo/fun.py
44 include CONTRIBUTING.md
55 include README.md
66 include requirements.txt
7 include test-requirements.txt
87
98 recursive-include doc *
10
11 graft git/test/fixtures
12 graft git/test/performance
9 recursive-exclude test *
1310
1411 global-exclude __pycache__ *.pyc
00 Metadata-Version: 1.2
11 Name: GitPython
2 Version: 3.1.3
2 Version: 3.1.7
33 Summary: Python Git Library
44 Home-page: https://github.com/gitpython-developers/GitPython
55 Author: Sebastian Thiel, Michael Trier
0 3.1.3
0 3.1.7
00 =========
11 Changelog
22 =========
3
4
5 3.1.7
6 =====
7
8 * Fix tutorial examples, which disappeared in 3.1.6 due to a missed path change.
9
10 3.1.6
11 =====
12
13 * Greatly reduced package size, see https://github.com/gitpython-developers/GitPython/pull/1031
14
15 3.1.5
16 =====
17
18 * rollback: package size was reduced significantly not placing tests into the package anymore.
19 See https://github.com/gitpython-developers/GitPython/issues/1030
20
21 3.1.4
22 =====
23
24 * all exceptions now keep track of their cause
25 * package size was reduced significantly not placing tests into the package anymore.
26
27 See the following for details:
28 https://github.com/gitpython-developers/gitpython/milestone/39?closed=1*
329
430 3.1.3
531 =====
99
1010 GitPython provides object model access to your git repository. This tutorial is composed of multiple sections, most of which explains a real-life usecase.
1111
12 All code presented here originated from `test_docs.py <https://github.com/gitpython-developers/GitPython/blob/master/git/test/test_docs.py>`_ to assure correctness. Knowing this should also allow you to more easily run the code for your own testing purposes, all you need is a developer installation of git-python.
12 All code presented here originated from `test_docs.py <https://github.com/gitpython-developers/GitPython/blob/master/test/test_docs.py>`_ to assure correctness. Knowing this should also allow you to more easily run the code for your own testing purposes, all you need is a developer installation of git-python.
1313
1414 Meet the Repo type
1515 ******************
1616
1717 The first step is to create a :class:`git.Repo <git.repo.base.Repo>` object to represent your repository.
1818
19 .. literalinclude:: ../../git/test/test_docs.py
19 .. literalinclude:: ../../test/test_docs.py
2020 :language: python
2121 :dedent: 8
2222 :start-after: # [1-test_init_repo_object]
2424
2525 In the above example, the directory ``self.rorepo.working_tree_dir`` equals ``/Users/mtrier/Development/git-python`` and is my working repository which contains the ``.git`` directory. You can also initialize GitPython with a *bare* repository.
2626
27 .. literalinclude:: ../../git/test/test_docs.py
27 .. literalinclude:: ../../test/test_docs.py
2828 :language: python
2929 :dedent: 8
3030 :start-after: # [2-test_init_repo_object]
3232
3333 A repo object provides high-level access to your data, it allows you to create and delete heads, tags and remotes and access the configuration of the repository.
3434
35 .. literalinclude:: ../../git/test/test_docs.py
35 .. literalinclude:: ../../test/test_docs.py
3636 :language: python
3737 :dedent: 8
3838 :start-after: # [3-test_init_repo_object]
4040
4141 Query the active branch, query untracked files or whether the repository data has been modified.
4242
43 .. literalinclude:: ../../git/test/test_docs.py
43 .. literalinclude:: ../../test/test_docs.py
4444 :language: python
4545 :dedent: 8
4646 :start-after: # [4-test_init_repo_object]
4848
4949 Clone from existing repositories or initialize new empty ones.
5050
51 .. literalinclude:: ../../git/test/test_docs.py
51 .. literalinclude:: ../../test/test_docs.py
5252 :language: python
5353 :dedent: 8
5454 :start-after: # [5-test_init_repo_object]
5656
5757 Archive the repository contents to a tar file.
5858
59 .. literalinclude:: ../../git/test/test_docs.py
59 .. literalinclude:: ../../test/test_docs.py
6060 :language: python
6161 :dedent: 8
6262 :start-after: # [6-test_init_repo_object]
6969
7070 Query relevant repository paths ...
7171
72 .. literalinclude:: ../../git/test/test_docs.py
72 .. literalinclude:: ../../test/test_docs.py
7373 :language: python
7474 :dedent: 8
7575 :start-after: # [7-test_init_repo_object]
7777
7878 :class:`Heads <git.refs.head.Head>` Heads are branches in git-speak. :class:`References <git.refs.reference.Reference>` are pointers to a specific commit or to other references. Heads and :class:`Tags <git.refs.tag.TagReference>` are a kind of references. GitPython allows you to query them rather intuitively.
7979
80 .. literalinclude:: ../../git/test/test_docs.py
80 .. literalinclude:: ../../test/test_docs.py
8181 :language: python
8282 :dedent: 8
8383 :start-after: # [8-test_init_repo_object]
8585
8686 You can also create new heads ...
8787
88 .. literalinclude:: ../../git/test/test_docs.py
88 .. literalinclude:: ../../test/test_docs.py
8989 :language: python
9090 :dedent: 8
9191 :start-after: # [9-test_init_repo_object]
9393
9494 ... and tags ...
9595
96 .. literalinclude:: ../../git/test/test_docs.py
96 .. literalinclude:: ../../test/test_docs.py
9797 :language: python
9898 :dedent: 8
9999 :start-after: # [10-test_init_repo_object]
101101
102102 You can traverse down to :class:`git objects <git.objects.base.Object>` through references and other objects. Some objects like :class:`commits <git.objects.commit.Commit>` have additional meta-data to query.
103103
104 .. literalinclude:: ../../git/test/test_docs.py
104 .. literalinclude:: ../../test/test_docs.py
105105 :language: python
106106 :dedent: 8
107107 :start-after: # [11-test_init_repo_object]
109109
110110 :class:`Remotes <git.remote.Remote>` allow to handle fetch, pull and push operations, while providing optional real-time progress information to :class:`progress delegates <git.util.RemoteProgress>`.
111111
112 .. literalinclude:: ../../git/test/test_docs.py
112 .. literalinclude:: ../../test/test_docs.py
113113 :language: python
114114 :dedent: 8
115115 :start-after: # [12-test_init_repo_object]
117117
118118 The :class:`index <git.index.base.IndexFile>` is also called stage in git-speak. It is used to prepare new commits, and can be used to keep results of merge operations. Our index implementation allows to stream date into the index, which is useful for bare repositories that do not have a working tree.
119119
120 .. literalinclude:: ../../git/test/test_docs.py
120 .. literalinclude:: ../../test/test_docs.py
121121 :language: python
122122 :dedent: 8
123123 :start-after: # [13-test_init_repo_object]
125125
126126 :class:`Submodules <git.objects.submodule.Submodule>` represent all aspects of git submodules, which allows you query all of their related information, and manipulate in various ways.
127127
128 .. literalinclude:: ../../git/test/test_docs.py
128 .. literalinclude:: ../../test/test_docs.py
129129 :language: python
130130 :dedent: 8
131131 :start-after: # [14-test_init_repo_object]
137137
138138 :class:`References <git.refs.reference.Reference>` are the tips of your commit graph from which you can easily examine the history of your project.
139139
140 .. literalinclude:: ../../git/test/test_docs.py
140 .. literalinclude:: ../../test/test_docs.py
141141 :language: python
142142 :dedent: 8
143143 :start-after: # [1-test_references_and_objects]
145145
146146 :class:`Tags <git.refs.tag.TagReference>` are (usually immutable) references to a commit and/or a tag object.
147147
148 .. literalinclude:: ../../git/test/test_docs.py
148 .. literalinclude:: ../../test/test_docs.py
149149 :language: python
150150 :dedent: 8
151151 :start-after: # [2-test_references_and_objects]
153153
154154 A :class:`symbolic reference <git.refs.symbolic.SymbolicReference>` is a special case of a reference as it points to another reference instead of a commit.
155155
156 .. literalinclude:: ../../git/test/test_docs.py
156 .. literalinclude:: ../../test/test_docs.py
157157 :language: python
158158 :dedent: 8
159159 :start-after: # [3-test_references_and_objects]
161161
162162 Access the :class:`reflog <git.refs.log.RefLog>` easily.
163163
164 .. literalinclude:: ../../git/test/test_docs.py
164 .. literalinclude:: ../../test/test_docs.py
165165 :language: python
166166 :dedent: 8
167167 :start-after: # [4-test_references_and_objects]
171171 ********************
172172 You can easily create and delete :class:`reference types <git.refs.reference.Reference>` or modify where they point to.
173173
174 .. literalinclude:: ../../git/test/test_docs.py
174 .. literalinclude:: ../../test/test_docs.py
175175 :language: python
176176 :dedent: 8
177177 :start-after: # [5-test_references_and_objects]
179179
180180 Create or delete :class:`tags <git.refs.tag.TagReference>` the same way except you may not change them afterwards.
181181
182 .. literalinclude:: ../../git/test/test_docs.py
182 .. literalinclude:: ../../test/test_docs.py
183183 :language: python
184184 :dedent: 8
185185 :start-after: # [6-test_references_and_objects]
187187
188188 Change the :class:`symbolic reference <git.refs.symbolic.SymbolicReference>` to switch branches cheaply (without adjusting the index or the working tree).
189189
190 .. literalinclude:: ../../git/test/test_docs.py
190 .. literalinclude:: ../../test/test_docs.py
191191 :language: python
192192 :dedent: 8
193193 :start-after: # [7-test_references_and_objects]
201201
202202 In GitPython, all objects can be accessed through their common base, can be compared and hashed. They are usually not instantiated directly, but through references or specialized repository functions.
203203
204 .. literalinclude:: ../../git/test/test_docs.py
204 .. literalinclude:: ../../test/test_docs.py
205205 :language: python
206206 :dedent: 8
207207 :start-after: # [8-test_references_and_objects]
209209
210210 Common fields are ...
211211
212 .. literalinclude:: ../../git/test/test_docs.py
212 .. literalinclude:: ../../test/test_docs.py
213213 :language: python
214214 :dedent: 8
215215 :start-after: # [9-test_references_and_objects]
217217
218218 :class:`Index objects <git.objects.base.IndexObject>` are objects that can be put into git's index. These objects are trees, blobs and submodules which additionally know about their path in the file system as well as their mode.
219219
220 .. literalinclude:: ../../git/test/test_docs.py
220 .. literalinclude:: ../../test/test_docs.py
221221 :language: python
222222 :dedent: 8
223223 :start-after: # [10-test_references_and_objects]
225225
226226 Access :class:`blob <git.objects.blob.Blob>` data (or any object data) using streams.
227227
228 .. literalinclude:: ../../git/test/test_docs.py
228 .. literalinclude:: ../../test/test_docs.py
229229 :language: python
230230 :dedent: 8
231231 :start-after: # [11-test_references_and_objects]
239239
240240 Obtain commits at the specified revision
241241
242 .. literalinclude:: ../../git/test/test_docs.py
242 .. literalinclude:: ../../test/test_docs.py
243243 :language: python
244244 :dedent: 8
245245 :start-after: # [12-test_references_and_objects]
247247
248248 Iterate 50 commits, and if you need paging, you can specify a number of commits to skip.
249249
250 .. literalinclude:: ../../git/test/test_docs.py
250 .. literalinclude:: ../../test/test_docs.py
251251 :language: python
252252 :dedent: 8
253253 :start-after: # [13-test_references_and_objects]
255255
256256 A commit object carries all sorts of meta-data
257257
258 .. literalinclude:: ../../git/test/test_docs.py
258 .. literalinclude:: ../../test/test_docs.py
259259 :language: python
260260 :dedent: 8
261261 :start-after: # [14-test_references_and_objects]
263263
264264 Note: date time is represented in a ``seconds since epoch`` format. Conversion to human readable form can be accomplished with the various `time module <http://docs.python.org/library/time.html>`_ methods.
265265
266 .. literalinclude:: ../../git/test/test_docs.py
266 .. literalinclude:: ../../test/test_docs.py
267267 :language: python
268268 :dedent: 8
269269 :start-after: # [15-test_references_and_objects]
271271
272272 You can traverse a commit's ancestry by chaining calls to ``parents``
273273
274 .. literalinclude:: ../../git/test/test_docs.py
274 .. literalinclude:: ../../test/test_docs.py
275275 :language: python
276276 :dedent: 8
277277 :start-after: # [16-test_references_and_objects]
284284
285285 A :class:`tree <git.objects.tree.Tree>` records pointers to the contents of a directory. Let's say you want the root tree of the latest commit on the master branch
286286
287 .. literalinclude:: ../../git/test/test_docs.py
287 .. literalinclude:: ../../test/test_docs.py
288288 :language: python
289289 :dedent: 8
290290 :start-after: # [17-test_references_and_objects]
292292
293293 Once you have a tree, you can get its contents
294294
295 .. literalinclude:: ../../git/test/test_docs.py
295 .. literalinclude:: ../../test/test_docs.py
296296 :language: python
297297 :dedent: 8
298298 :start-after: # [18-test_references_and_objects]
300300
301301 It is useful to know that a tree behaves like a list with the ability to query entries by name
302302
303 .. literalinclude:: ../../git/test/test_docs.py
303 .. literalinclude:: ../../test/test_docs.py
304304 :language: python
305305 :dedent: 8
306306 :start-after: # [19-test_references_and_objects]
308308
309309 There is a convenience method that allows you to get a named sub-object from a tree with a syntax similar to how paths are written in a posix system
310310
311 .. literalinclude:: ../../git/test/test_docs.py
311 .. literalinclude:: ../../test/test_docs.py
312312 :language: python
313313 :dedent: 8
314314 :start-after: # [20-test_references_and_objects]
316316
317317 You can also get a commit's root tree directly from the repository
318318
319 .. literalinclude:: ../../git/test/test_docs.py
319 .. literalinclude:: ../../test/test_docs.py
320320 :language: python
321321 :dedent: 8
322322 :start-after: # [21-test_references_and_objects]
324324
325325 As trees allow direct access to their intermediate child entries only, use the traverse method to obtain an iterator to retrieve entries recursively
326326
327 .. literalinclude:: ../../git/test/test_docs.py
327 .. literalinclude:: ../../test/test_docs.py
328328 :language: python
329329 :dedent: 8
330330 :start-after: # [22-test_references_and_objects]
337337 The git index is the stage containing changes to be written with the next commit or where merges finally have to take place. You may freely access and manipulate this information using the :class:`IndexFile <git.index.base.IndexFile>` object.
338338 Modify the index with ease
339339
340 .. literalinclude:: ../../git/test/test_docs.py
340 .. literalinclude:: ../../test/test_docs.py
341341 :language: python
342342 :dedent: 8
343343 :start-after: # [23-test_references_and_objects]
345345
346346 Create new indices from other trees or as result of a merge. Write that result to a new index file for later inspection.
347347
348 .. literalinclude:: ../../git/test/test_docs.py
348 .. literalinclude:: ../../test/test_docs.py
349349 :language: python
350350 :dedent: 8
351351 :start-after: # [24-test_references_and_objects]
356356
357357 :class:`Remotes <git.remote.Remote>` are used as alias for a foreign repository to ease pushing to and fetching from them
358358
359 .. literalinclude:: ../../git/test/test_docs.py
359 .. literalinclude:: ../../test/test_docs.py
360360 :language: python
361361 :dedent: 8
362362 :start-after: # [25-test_references_and_objects]
364364
365365 You can easily access configuration information for a remote by accessing options as if they where attributes. The modification of remote configuration is more explicit though.
366366
367 .. literalinclude:: ../../git/test/test_docs.py
367 .. literalinclude:: ../../test/test_docs.py
368368 :language: python
369369 :dedent: 8
370370 :start-after: # [26-test_references_and_objects]
398398 ******************
399399 :class:`Submodules <git.objects.submodule.base.Submodule>` can be conveniently handled using the methods provided by GitPython, and as an added benefit, GitPython provides functionality which behave smarter and less error prone than its original c-git implementation, that is GitPython tries hard to keep your repository consistent when updating submodules recursively or adjusting the existing configuration.
400400
401 .. literalinclude:: ../../git/test/test_docs.py
401 .. literalinclude:: ../../test/test_docs.py
402402 :language: python
403403 :dedent: 8
404404 :start-after: # [1-test_submodules]
423423
424424 Diffs can be made between the Index and Trees, Index and the working tree, trees and trees as well as trees and the working copy. If commits are involved, their tree will be used implicitly.
425425
426 .. literalinclude:: ../../git/test/test_docs.py
426 .. literalinclude:: ../../test/test_docs.py
427427 :language: python
428428 :dedent: 8
429429 :start-after: # [27-test_references_and_objects]
431431
432432 The item returned is a DiffIndex which is essentially a list of Diff objects. It provides additional filtering to ease finding what you might be looking for.
433433
434 .. literalinclude:: ../../git/test/test_docs.py
434 .. literalinclude:: ../../test/test_docs.py
435435 :language: python
436436 :dedent: 8
437437 :start-after: # [28-test_references_and_objects]
455455 ******************
456456 To switch between branches similar to ``git checkout``, you effectively need to point your HEAD symbolic reference to the new branch and reset your index and working copy to match. A simple manual way to do it is the following one
457457
458 .. literalinclude:: ../../git/test/test_docs.py
458 .. literalinclude:: ../../test/test_docs.py
459459 :language: python
460460 :dedent: 8
461461 :start-after: # [29-test_references_and_objects]
463463
464464 The previous approach would brutally overwrite the user's changes in the working copy and index though and is less sophisticated than a ``git-checkout``. The latter will generally prevent you from destroying your work. Use the safer approach as follows.
465465
466 .. literalinclude:: ../../git/test/test_docs.py
466 .. literalinclude:: ../../test/test_docs.py
467467 :language: python
468468 :dedent: 8
469469 :start-after: # [30-test_references_and_objects]
474474
475475 In this example, we will initialize an empty repository, add an empty file to the index, and commit the change.
476476
477 .. literalinclude:: ../../git/test/test_docs.py
477 .. literalinclude:: ../../test/test_docs.py
478478 :language: python
479479 :dedent: 8
480480 :start-after: def test_add_file_and_commit
486486 ******************
487487 In case you are missing functionality as it has not been wrapped, you may conveniently use the :class:`git <git.cmd.Git>` command directly. It is owned by each repository instance.
488488
489 .. literalinclude:: ../../git/test/test_docs.py
489 .. literalinclude:: ../../test/test_docs.py
490490 :language: python
491491 :dedent: 8
492492 :start-after: # [31-test_references_and_objects]
1111 import os.path as osp
1212
1313
14 __version__ = '3.1.3'
14 __version__ = '3.1.7'
1515
1616
1717 #{ Initialization
1818 def _init_externals():
1919 """Initialize external projects by putting them into the path"""
20 if __version__ == '3.1.3' and 'PYOXIDIZER' not in os.environ:
20 if __version__ == '3.1.7' and 'PYOXIDIZER' not in os.environ:
2121 sys.path.insert(0, osp.join(osp.dirname(__file__), 'ext', 'gitdb'))
2222
2323 try:
2424 import gitdb
25 except ImportError:
26 raise ImportError("'gitdb' could not be found in your PYTHONPATH")
25 except ImportError as e:
26 raise ImportError("'gitdb' could not be found in your PYTHONPATH") from e
2727 # END verify import
2828
2929 #} END initialization
5353 rmtree,
5454 )
5555 except GitError as exc:
56 raise ImportError('%s: %s' % (exc.__class__.__name__, exc))
56 raise ImportError('%s: %s' % (exc.__class__.__name__, exc)) from exc
5757
5858 #} END imports
5959
8181 try:
8282 refresh()
8383 except Exception as exc:
84 raise ImportError('Failed to initialize: {0}'.format(exc))
84 raise ImportError('Failed to initialize: {0}'.format(exc)) from exc
8585 #################
8282 handler(line)
8383 except Exception as ex:
8484 log.error("Pumping %r of cmd(%s) failed due to: %r", name, cmdline, ex)
85 raise CommandError(['<%s-pump>' % name] + cmdline, ex)
85 raise CommandError(['<%s-pump>' % name] + cmdline, ex) from ex
8686 finally:
8787 stream.close()
8888
731731 **subprocess_kwargs
732732 )
733733 except cmd_not_found_exception as err:
734 raise GitCommandNotFound(command, err)
734 raise GitCommandNotFound(command, err) from err
735735
736736 if as_process:
737737 return self.AutoInterrupt(proc, command)
981981 else:
982982 try:
983983 index = ext_args.index(insert_after_this_arg)
984 except ValueError:
984 except ValueError as err:
985985 raise ValueError("Couldn't find argument '%s' in args %s to insert cmd options after"
986 % (insert_after_this_arg, str(ext_args)))
986 % (insert_after_this_arg, str(ext_args))) from err
987987 # end handle error
988988 args = ext_args[:index + 1] + opt_args + ext_args[index + 1:]
989989 # end handle opts_kwargs
5252 try:
5353 hexsha, _typename, _size = self._git.get_object_header(partial_hexsha)
5454 return hex_to_bin(hexsha)
55 except (GitCommandError, ValueError):
56 raise BadObject(partial_hexsha)
55 except (GitCommandError, ValueError) as e:
56 raise BadObject(partial_hexsha) from e
5757 # END handle exceptions
5858
5959 #} END interface
419419 rval = None
420420 try:
421421 proc.stdin.write(("%s\n" % filepath).encode(defenc))
422 except IOError:
422 except IOError as e:
423423 # pipe broke, usually because some error happened
424 raise fmakeexc()
424 raise fmakeexc() from e
425425 # END write exception handling
426426 proc.stdin.flush()
427427 if read_from_stdout:
953953 if not skip_hooks:
954954 run_commit_hook('post-commit', self)
955955 return rval
956
956
957957 def _write_commit_editmsg(self, message):
958958 with open(self._commit_editmsg_filepath(), "wb") as commit_editmsg_file:
959959 commit_editmsg_file.write(message.encode(defenc))
8181 close_fds=is_posix,
8282 creationflags=PROC_CREATIONFLAGS,)
8383 except Exception as ex:
84 raise HookExecutionError(hp, ex)
84 raise HookExecutionError(hp, ex) from ex
8585 else:
8686 stdout = []
8787 stderr = []
120120 # default submodule values
121121 try:
122122 self.path = reader.get('path')
123 except cp.NoSectionError:
123 except cp.NoSectionError as e:
124124 raise ValueError("This submodule instance does not exist anymore in '%s' file"
125 % osp.join(self.repo.working_tree_dir, '.gitmodules'))
125 % osp.join(self.repo.working_tree_dir, '.gitmodules')) from e
126126 # end
127127 self._url = reader.get('url')
128128 # git-python extension values - optional
188188 assert parent_commit is not None, "need valid parent_commit in bare repositories"
189189 try:
190190 fp_module = cls._sio_modules(parent_commit)
191 except KeyError:
191 except KeyError as e:
192192 raise IOError("Could not find %s file in the tree of parent commit %s" %
193 (cls.k_modules_file, parent_commit))
193 (cls.k_modules_file, parent_commit)) from e
194194 # END handle exceptions
195195 # END handle non-bare working tree
196196
515515 if not dry_run and osp.isdir(checkout_module_abspath):
516516 try:
517517 os.rmdir(checkout_module_abspath)
518 except OSError:
518 except OSError as e:
519519 raise OSError("Module directory at %r does already exist and is non-empty"
520 % checkout_module_abspath)
520 % checkout_module_abspath) from e
521521 # END handle OSError
522522 # END handle directory removal
523523
736736 del(index.entries[ekey])
737737 nentry = git.IndexEntry(entry[:3] + (module_checkout_path,) + entry[4:])
738738 index.entries[tekey] = nentry
739 except KeyError:
740 raise InvalidGitRepositoryError("Submodule's entry at %r did not exist" % (self.path))
739 except KeyError as e:
740 raise InvalidGitRepositoryError("Submodule's entry at %r did not exist" % (self.path)) from e
741741 # END handle submodule doesn't exist
742742
743743 # update configuration
870870 rmtree(wtd)
871871 except Exception as ex:
872872 if HIDE_WINDOWS_KNOWN_ERRORS:
873 raise SkipTest("FIXME: fails with: PermissionError\n {}".format(ex))
873 raise SkipTest("FIXME: fails with: PermissionError\n {}".format(ex)) from ex
874874 raise
875875 # END delete tree if possible
876876 # END handle force
881881 rmtree(git_dir)
882882 except Exception as ex:
883883 if HIDE_WINDOWS_KNOWN_ERRORS:
884 raise SkipTest("FIXME: fails with: PermissionError\n %s", ex)
884 raise SkipTest("FIXME: fails with: PermissionError\n %s", ex) from ex
885885 else:
886886 raise
887887 # end handle separate bare repository
10451045 if repo != self.repo:
10461046 return repo
10471047 # END handle repo uninitialized
1048 except (InvalidGitRepositoryError, NoSuchPathError):
1049 raise InvalidGitRepositoryError("No valid repository at %s" % module_checkout_abspath)
1048 except (InvalidGitRepositoryError, NoSuchPathError) as e:
1049 raise InvalidGitRepositoryError("No valid repository at %s" % module_checkout_abspath) from e
10501050 else:
10511051 raise InvalidGitRepositoryError("Repository at %r was not yet checked out" % module_checkout_abspath)
10521052 # END handle exceptions
202202 path = join_path(self.path, name)
203203 try:
204204 yield self._map_id_to_type[mode >> 12](self.repo, binsha, mode, path)
205 except KeyError:
206 raise TypeError("Unknown mode %o found in tree data for path '%s'" % (mode, path))
205 except KeyError as e:
206 raise TypeError("Unknown mode %o found in tree data for path '%s'" % (mode, path)) from e
207207 # END for each item
208208
209209 def join(self, file):
202202 # still here ? fail
203203 raise ValueError("no format matched")
204204 # END handle format
205 except Exception:
206 raise ValueError("Unsupported date format: %s" % string_date)
205 except Exception as e:
206 raise ValueError("Unsupported date format: %s" % string_date) from e
207207 # END handle exceptions
208208
209209
218218 else:
219219 try:
220220 invalid_type = self.repo.rev_parse(commit).type != Commit.type
221 except (BadObject, BadName):
222 raise ValueError("Invalid object: %s" % commit)
221 except (BadObject, BadName) as e:
222 raise ValueError("Invalid object: %s" % commit) from e
223223 # END handle exception
224224 # END verify type
225225
300300 try:
301301 obj = self.repo.rev_parse(ref + "^{}") # optionally deref tags
302302 write_value = obj.hexsha
303 except (BadObject, BadName):
304 raise ValueError("Could not extract object from %s" % ref)
303 except (BadObject, BadName) as e:
304 raise ValueError("Could not extract object from %s" % ref) from e
305305 # END end try string
306306 else:
307307 raise ValueError("Unrecognized Value: %r" % ref)
145145 # control character handling
146146 try:
147147 flags |= cls._flag_map[control_character]
148 except KeyError:
149 raise ValueError("Control character %r unknown as parsed from line %r" % (control_character, line))
148 except KeyError as e:
149 raise ValueError("Control character %r unknown as parsed from line %r" % (control_character, line)) from e
150150 # END handle control character
151151
152152 # from_to handling
295295 try:
296296 _new_hex_sha, _fetch_operation, fetch_note = fetch_line.split("\t")
297297 ref_type_name, fetch_note = fetch_note.split(' ', 1)
298 except ValueError: # unpack error
299 raise ValueError("Failed to parse FETCH_HEAD line: %r" % fetch_line)
298 except ValueError as e: # unpack error
299 raise ValueError("Failed to parse FETCH_HEAD line: %r" % fetch_line) from e
300300
301301 # parse flags from control_character
302302 flags = 0
303303 try:
304304 flags |= cls._flag_map[control_character]
305 except KeyError:
306 raise ValueError("Control character %r unknown as parsed from line %r" % (control_character, line))
305 except KeyError as e:
306 raise ValueError("Control character %r unknown as parsed from line %r" % (control_character, line)) from e
307307 # END control char exception handling
308308
309309 # parse operation string for more info - makes no sense for symbolic refs, but we parse it anyway
340340 :raise ValueError: If no such submodule exists"""
341341 try:
342342 return self.submodules[name]
343 except IndexError:
344 raise ValueError("Didn't find submodule named %r" % name)
343 except IndexError as e:
344 raise ValueError("Didn't find submodule named %r" % name) from e
345345 # END exception handling
346346
347347 def create_submodule(self, *args, **kwargs):
250250 try:
251251 # transform reversed index into the format of our revlog
252252 revlog_index = -(int(output_type) + 1)
253 except ValueError:
253 except ValueError as e:
254254 # TODO: Try to parse the other date options, using parse_date
255255 # maybe
256 raise NotImplementedError("Support for additional @{...} modes not implemented")
256 raise NotImplementedError("Support for additional @{...} modes not implemented") from e
257257 # END handle revlog index
258258
259259 try:
260260 entry = ref.log_entry(revlog_index)
261 except IndexError:
262 raise IndexError("Invalid revlog index: %i" % revlog_index)
261 except IndexError as e:
262 raise IndexError("Invalid revlog index: %i" % revlog_index) from e
263263 # END handle index out of bound
264264
265265 obj = Object.new_from_sha(repo, hex_to_bin(entry.newhexsha))
323323 else:
324324 raise ValueError("Invalid token: %r" % token)
325325 # END end handle tag
326 except (IndexError, AttributeError):
327 raise BadName("Invalid revision spec '%s' - not enough parent commits to reach '%s%i'" % (rev, token, num))
326 except (IndexError, AttributeError) as e:
327 raise BadName(
328 "Invalid revision spec '%s' - not enough "
329 "parent commits to reach '%s%i'" % (rev, token, num)) from e
328330 # END exception handling
329331 # END parse loop
330332
+0
-5
git/test/__init__.py less more
0 # __init__.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
+0
-3
git/test/fixtures/.gitconfig less more
0 [alias]
1 rbi = "!g() { git rebase -i origin/${1:-master} ; } ; g"
2 expush = "!f() { git branch -f tmp ; { git rbi $1 && git push ; } ; git reset --hard tmp ; git rebase origin/${1:-master}; } ; f"
+0
-131
git/test/fixtures/blame less more
0 634396b2f541a9f2d58b00be1a07f0c358b999b3 1 1 7
1 author Tom Preston-Werner
2 author-mail <tom@mojombo.com>
3 author-time 1191997100
4 author-tz -0700
5 committer Tom Preston-Werner
6 committer-mail <tom@mojombo.com>
7 committer-time 1191997100
8 committer-tz -0700
9 filename lib/grit.rb
10 summary initial grit setup
11 boundary
12 $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
13 634396b2f541a9f2d58b00be1a07f0c358b999b3 2 2
14
15 634396b2f541a9f2d58b00be1a07f0c358b999b3 3 3
16 # core
17 634396b2f541a9f2d58b00be1a07f0c358b999b3 4 4
18
19 634396b2f541a9f2d58b00be1a07f0c358b999b3 5 5
20 # stdlib
21 634396b2f541a9f2d58b00be1a07f0c358b999b3 6 6
22
23 634396b2f541a9f2d58b00be1a07f0c358b999b3 7 7
24 # internal requires
25 3b1930208a82457747d76729ae088e90edca4673 8 8 1
26 author Tom Preston-Werner
27 author-mail <tom@mojombo.com>
28 author-time 1192267241
29 author-tz -0700
30 committer Tom Preston-Werner
31 committer-mail <tom@mojombo.com>
32 committer-time 1192267241
33 committer-tz -0700
34 filename lib/grit.rb
35 summary big refactor to do lazy loading
36 require 'grit/lazy'
37 4c8124ffcf4039d292442eeccabdeca5af5c5017 8 9 1
38 author Tom Preston-Werner
39 author-mail <tom@mojombo.com>
40 author-time 1191999972
41 author-tz -0700
42 committer Tom Preston-Werner
43 committer-mail <tom@mojombo.com>
44 committer-time 1191999972
45 committer-tz -0700
46 filename lib/grit.rb
47 summary implement Grit#heads
48 require 'grit/errors'
49 d01a4cfad6ea50285c4710243e3cbe019d381eba 9 10 1
50 author Tom Preston-Werner
51 author-mail <tom@mojombo.com>
52 author-time 1192032303
53 author-tz -0700
54 committer Tom Preston-Werner
55 committer-mail <tom@mojombo.com>
56 committer-time 1192032303
57 committer-tz -0700
58 filename lib/grit.rb
59 summary convert to Grit module, refactor to be more OO
60 require 'grit/git'
61 4c8124ffcf4039d292442eeccabdeca5af5c5017 9 11 1
62 require 'grit/head'
63 a47fd41f3aa4610ea527dcc1669dfdb9c15c5425 10 12 1
64 author Tom Preston-Werner
65 author-mail <tom@mojombo.com>
66 author-time 1192002639
67 author-tz -0700
68 committer Tom Preston-Werner
69 committer-mail <tom@mojombo.com>
70 committer-time 1192002639
71 committer-tz -0700
72 filename lib/grit.rb
73 summary add more comments throughout
74 require 'grit/commit'
75 b17b974691f0a26f26908495d24d9c4c718920f8 13 13 1
76 author Tom Preston-Werner
77 author-mail <tom@mojombo.com>
78 author-time 1192271832
79 author-tz -0700
80 committer Tom Preston-Werner
81 committer-mail <tom@mojombo.com>
82 committer-time 1192271832
83 committer-tz -0700
84 filename lib/grit.rb
85 summary started implementing Tree
86 require 'grit/tree'
87 74fd66519e983a0f29e16a342a6059dbffe36020 14 14 1
88 author Tom Preston-Werner
89 author-mail <tom@mojombo.com>
90 author-time 1192317005
91 author-tz -0700
92 committer Tom Preston-Werner
93 committer-mail <tom@mojombo.com>
94 committer-time 1192317005
95 committer-tz -0700
96 filename lib/grit.rb
97 summary add Blob
98 require 'grit/blob'
99 d01a4cfad6ea50285c4710243e3cbe019d381eba 12 15 1
100 require 'grit/repo'
101 634396b2f541a9f2d58b00be1a07f0c358b999b3 9 16 1
102
103 d01a4cfad6ea50285c4710243e3cbe019d381eba 14 17 1
104 module Grit
105 b6e1b765e0c15586a2c5b9832854f95defd71e1f 18 18 6
106 author Tom Preston-Werner
107 author-mail <tom@mojombo.com>
108 author-time 1192860483
109 author-tz -0700
110 committer Tom Preston-Werner
111 committer-mail <tom@mojombo.com>
112 committer-time 1192860483
113 committer-tz -0700
114 filename lib/grit.rb
115 summary implement Repo.init_bare
116 class << self
117 b6e1b765e0c15586a2c5b9832854f95defd71e1f 19 19
118 attr_accessor :debug
119 b6e1b765e0c15586a2c5b9832854f95defd71e1f 20 20
120 end
121 b6e1b765e0c15586a2c5b9832854f95defd71e1f 21 21
122
123 b6e1b765e0c15586a2c5b9832854f95defd71e1f 22 22
124 self.debug = false
125 b6e1b765e0c15586a2c5b9832854f95defd71e1f 23 23
126
127 634396b2f541a9f2d58b00be1a07f0c358b999b3 11 24 2
128 VERSION = '1.0.0'
129 634396b2f541a9f2d58b00be1a07f0c358b999b3 12 25
130 end
git/test/fixtures/blame_binary less more
Binary diff not shown
+0
-177
git/test/fixtures/blame_complex_revision less more
0 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 1 1 83
1 author Sebastian Thiel
2 author-mail <byronimo@gmail.com>
3 author-time 1420715996
4 author-tz +0100
5 committer Sebastian Thiel
6 committer-mail <byronimo@gmail.com>
7 committer-time 1420716149
8 committer-tz +0100
9 summary Fixed PY3 support.
10 boundary
11 filename README.md
12 ## GitPython
13 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 2 2
14
15 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 3 3
16 GitPython is a python library used to interact with git repositories, high-level like git-porcelain, or low-level like git-plumbing.
17 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 4 4
18
19 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 5 5
20 It provides abstractions of git objects for easy access of repository data, and additionally allows you to access the git repository more directly using either a pure python implementation, or the faster, but more resource intensive git command implementation.
21 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 6 6
22
23 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 7 7
24 The object database implementation is optimized for handling large quantities of objects and large datasets, which is achieved by using low-level structures and data streaming.
25 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 8 8
26
27 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 9 9
28 ### REQUIREMENTS
29 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 10 10
30
31 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 11 11
32 * Git ( tested with 1.8.3.4 )
33 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 12 12
34 * Python Nose - used for running the tests
35 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 13 13
36 - Tested with nose 1.3.0
37 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 14 14
38 * Mock by Michael Foord used for tests
39 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 15 15
40 - Tested with 1.0.1
41 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 16 16
42 * Coverage - used for tests coverage
43 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 17 17
44
45 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 18 18
46 The list of dependencies are listed in /requirements.txt and /test-requirements.txt. The installer takes care of installing them for you though.
47 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 19 19
48
49 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 20 20
50 ### INSTALL
51 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 21 21
52
53 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 22 22
54 [![Latest Version](https://pypip.in/version/GitPython/badge.svg)](https://pypi.python.org/pypi/GitPython/)
55 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 23 23
56 [![Supported Python Versions](https://pypip.in/py_versions/GitPython/badge.svg)](https://pypi.python.org/pypi/GitPython/)
57 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 24 24
58
59 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 25 25
60 If you have downloaded the source code:
61 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 26 26
62
63 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 27 27
64 python setup.py install
65 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 28 28
66
67 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 29 29
68 or if you want to obtain a copy from the Pypi repository:
69 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 30 30
70
71 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 31 31
72 pip install gitpython
73 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 32 32
74
75 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 33 33
76 Both commands will install the required package dependencies.
77 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 34 34
78
79 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 35 35
80 A distribution package can be obtained for manual installation at:
81 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 36 36
82
83 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 37 37
84 http://pypi.python.org/pypi/GitPython
85 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 38 38
86
87 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 39 39
88 ### RUNNING TESTS
89 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 40 40
90
91 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 41 41
92 The easiest way to run test is by using [tox](https://pypi.python.org/pypi/tox) a wrapper around virtualenv. It will take care of setting up environnements with the proper dependencies installed and execute test commands. To install it simply:
93 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 42 42
94
95 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 43 43
96 pip install tox
97 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 44 44
98
99 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 45 45
100 Then run:
101 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 46 46
102
103 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 47 47
104 tox
105 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 48 48
106
107 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 49 49
108 ### SOURCE
109 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 50 50
110
111 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 51 51
112 GitPython's git repo is available on GitHub, which can be browsed at [github](https://github.com/gitpython-developers/GitPython) and cloned like that:
113 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 52 52
114
115 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 53 53
116 git clone git://github.com/gitpython-developers/GitPython.git git-python
117 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 54 54
118
119 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 55 55
120
121 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 56 56
122 ### INFRASTRUCTURE
123 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 57 57
124
125 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 58 58
126 * [User Documentation](http://gitpython.readthedocs.org)
127 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 59 59
128 * [Mailing List](http://groups.google.com/group/git-python)
129 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 60 60
130 * [Issue Tracker](https://github.com/gitpython-developers/GitPython/issues)
131 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 61 61
132
133 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 62 62
134 ### LICENSE
135 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 63 63
136
137 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 64 64
138 New BSD License. See the LICENSE file.
139 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 65 65
140
141 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 66 66
142 ### DEVELOPMENT STATUS
143 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 67 67
144
145 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 68 68
146 [![Build Status](https://travis-ci.org/gitpython-developers/GitPython.svg?branch=0.3)](https://travis-ci.org/gitpython-developers/GitPython)
147 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 69 69
148 [![Coverage Status](https://coveralls.io/repos/gitpython-developers/GitPython/badge.png?branch=master)](https://coveralls.io/r/gitpython-developers/GitPython?branch=master)
149 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 70 70
150 [![Documentation Status](https://readthedocs.org/projects/gitpython/badge/?version=stable)](https://readthedocs.org/projects/gitpython/?badge=stable)
151 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 71 71
152
153 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 72 72
154 Now that there seems to be a massive user base, this should be motivation enough to let git-python return to a proper state, which means
155 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 73 73
156
157 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 74 74
158 * no open pull requests
159 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 75 75
160 * no open issues describing bugs
161 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 76 76
162
163 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 77 77
164 #### FUTURE GOALS
165 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 78 78
166
167 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 79 79
168 There has been a lot of work in the master branch, which is the direction I want git-python to go. Namely, it should be able to freely mix and match the back-end used, depending on your requirements and environment.
169 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 80 80
170
171 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 81 81
172 * make new master work similarly to 0.3, but with the option to swap for at least one additional backend
173 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 82 82
174 * make a 1.0 release
175 e40ad6369bc74d01af4dc41d3a9b8e25ac2aa01e 83 83
176 * add backends as required
+0
-32
git/test/fixtures/blame_incremental less more
0 82b8902e033430000481eb355733cd7065342037 2 2 1
1 author Sebastian Thiel
2 author-mail <byronimo@gmail.com>
3 author-time 1270634931
4 author-tz +0200
5 committer Sebastian Thiel
6 committer-mail <byronimo@gmail.com>
7 committer-time 1270634931
8 committer-tz +0200
9 summary Used this release
10
11 for a first beta of the 0.2 branch of development
12 previous 501bf602abea7d21c3dbb409b435976e92033145 AUTHORS
13 filename AUTHORS
14 82b8902e033430000481eb355733cd7065342037 14 14 1
15 filename AUTHORS
16 c76852d0bff115720af3f27acdb084c59361e5f6 1 1 1
17 author Michael Trier
18 author-mail <mtrier@gmail.com>
19 author-time 1232829627
20 author-tz -0500
21 committer Michael Trier
22 committer-mail <mtrier@gmail.com>
23 committer-time 1232829627
24 committer-tz -0500
25 summary Lots of spring cleaning and added in Sphinx documentation.
26 previous bcd57e349c08bd7f076f8d6d2f39b702015358c1 AUTHORS
27 filename AUTHORS
28 c76852d0bff115720af3f27acdb084c59361e5f6 2 3 11
29 filename AUTHORS
30 c76852d0bff115720af3f27acdb084c59361e5f6 13 15 2
31 filename AUTHORS
+0
-33
git/test/fixtures/blame_incremental_2.11.1_plus less more
0 82b8902e033430000481eb355733cd7065342037 2 2 1
1 author Sebastian Thiel
2 author-mail <byronimo@gmail.com>
3 author-time 1270634931
4 author-tz +0200
5 committer Sebastian Thiel
6 committer-mail <byronimo@gmail.com>
7 committer-time 1270634931
8 committer-tz +0200
9 summary Used this release for a first beta of the 0.2 branch of development
10 previous 501bf602abea7d21c3dbb409b435976e92033145 AUTHORS
11 filename AUTHORS
12 82b8902e033430000481eb355733cd7065342037 14 14 1
13 previous 501bf602abea7d21c3dbb409b435976e92033145 AUTHORS
14 filename AUTHORS
15 c76852d0bff115720af3f27acdb084c59361e5f6 1 1 1
16 author Michael Trier
17 author-mail <mtrier@gmail.com>
18 author-time 1232829627
19 author-tz -0500
20 committer Michael Trier
21 committer-mail <mtrier@gmail.com>
22 committer-time 1232829627
23 committer-tz -0500
24 summary Lots of spring cleaning and added in Sphinx documentation.
25 previous bcd57e349c08bd7f076f8d6d2f39b702015358c1 AUTHORS
26 filename AUTHORS
27 c76852d0bff115720af3f27acdb084c59361e5f6 2 3 11
28 previous bcd57e349c08bd7f076f8d6d2f39b702015358c1 AUTHORS
29 filename AUTHORS
30 c76852d0bff115720af3f27acdb084c59361e5f6 13 15 2
31 previous bcd57e349c08bd7f076f8d6d2f39b702015358c1 AUTHORS
32 filename AUTHORS
+0
-6
git/test/fixtures/cat_file.py less more
0 import sys
1
2 with open(sys.argv[1]) as fd:
3 for line in fd.readlines():
4 sys.stdout.write(line)
5 sys.stderr.write(line)
+0
-1
git/test/fixtures/cat_file_blob less more
0 Hello world
+0
-1
git/test/fixtures/cat_file_blob_nl less more
0 Hello world
+0
-1
git/test/fixtures/cat_file_blob_size less more
0 11
+0
-6
git/test/fixtures/commit_invalid_data less more
0 tree 9f1a495d7d9692d24f5caedaa89f5c2c32d59368
1 parent 492ace2ffce0e426ebeb55e364e987bcf024dd3b
2 author E.Azer Ko√o√o√oculu <azer@kodfabrik.com> 1306710073 +0300
3 committer E.Azer Ko√o√o√oculu <azer@kodfabrik.com> 1306710073 +0300
4
5 add environjs
+0
-30
git/test/fixtures/commit_with_gpgsig less more
0 tree cefbccb4843d821183ae195e70a17c9938318945
1 parent 904435cf76a9bdd5eb41b1c4e049d5a64f3a8400
2 author Jon Mason <jon.mason@intel.com> 1367013117 -0700
3 committer Jon Mason <jon.mason@intel.com> 1368640702 -0700
4 gpgsig -----BEGIN PGP SIGNATURE-----
5 Version: GnuPG v1.4.11 (GNU/Linux)
6
7 iQIcBAABAgAGBQJRk8zMAAoJEG5mS6x6i9IjsTEP/0v2Wx/i7dqyKban6XMIhVdj
8 uI0DycfXqnCCZmejidzeao+P+cuK/ZAA/b9fU4MtwkDm2USvnIOrB00W0isxsrED
9 sdv6uJNa2ybGjxBolLrfQcWutxGXLZ1FGRhEvkPTLMHHvVriKoNFXcS7ewxP9MBf
10 NH97K2wauqA+J4BDLDHQJgADCOmLrGTAU+G1eAXHIschDqa6PZMH5nInetYZONDh
11 3SkOOv8VKFIF7gu8X7HC+7+Y8k8U0TW0cjlQ2icinwCc+KFoG6GwXS7u/VqIo1Yp
12 Tack6sxIdK7NXJhV5gAeAOMJBGhO0fHl8UUr96vGEKwtxyZhWf8cuIPOWLk06jA0
13 g9DpLqmy/pvyRfiPci+24YdYRBua/vta+yo/Lp85N7Hu/cpIh+q5WSLvUlv09Dmo
14 TTTG8Hf6s3lEej7W8z2xcNZoB6GwXd8buSDU8cu0I6mEO9sNtAuUOHp2dBvTA6cX
15 PuQW8jg3zofnx7CyNcd3KF3nh2z8mBcDLgh0Q84srZJCPRuxRcp9ylggvAG7iaNd
16 XMNvSK8IZtWLkx7k3A3QYt1cN4y1zdSHLR2S+BVCEJea1mvUE+jK5wiB9S4XNtKm
17 BX/otlTa8pNE3fWYBxURvfHnMY4i3HQT7Bc1QjImAhMnyo2vJk4ORBJIZ1FTNIhJ
18 JzJMZDRLQLFvnzqZuCjE
19 =przd
20 -----END PGP SIGNATURE-----
21
22 NTB: Multiple NTB client fix
23
24 Fix issue with adding multiple ntb client devices to the ntb virtual
25 bus. Previously, multiple devices would be added with the same name,
26 resulting in crashes. To get around this issue, add a unique number to
27 the device when it is added.
28
29 Signed-off-by: Jon Mason <jon.mason@intel.com>
+0
-54
git/test/fixtures/diff_2 less more
0 diff --git a/lib/grit/commit.rb b/lib/grit/commit.rb
1 index a093bb1db8e884cccf396b297259181d1caebed4..80fd3d527f269ecbd570b65b8e21fd85baedb6e9 100644
2 --- a/lib/grit/com mit.rb
3 +++ b/lib/grit/com mit.rb
4 @@ -156,12 +156,8 @@ module Grit
5
6 def diffs
7 if parents.empty?
8 - diff = @repo.git.show({:full_index => true, :pretty => 'raw'}, @id)
9 - if diff =~ /diff --git a/
10 - diff = diff.sub(/.+?(diff --git a)/m, '\1')
11 - else
12 - diff = ''
13 - end
14 + diff = @repo.git.show({:full_index => true, :pretty => 'raw'}, @id)
15 + diff = diff.sub(/.+?(diff --git a)/m, '\1')
16 Diff.list_from_string(@repo, diff)
17 else
18 self.class.diff(@repo, parents.first.id, @id)
19 diff --git a/test/fixtures/show_empty_commit b/test/fixtures/show_empty_commit
20 deleted file mode 100644
21 index ea25e32a409fdf74c1b9268820108d1c16dcc553..0000000000000000000000000000000000000000
22 --- a/test/fixtures/show_empty_commit
23 +++ /dev/null
24 @@ -1,6 +0,0 @@
25 -commit 1e3824339762bd48316fe87bfafc853732d43264
26 -tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904
27 -author Tom Preston-Werner <tom@mojombo.com> 1157392833 +0000
28 -committer Tom Preston-Werner <tom@mojombo.com> 1157392833 +0000
29 -
30 - initial directory structure
31 diff --git a/test/test_commit.rb b/test/test_commit.rb
32 index fdeb9000089b052f0b31a845e0173e9b089e06a0..bdbc450e08084d7d611e985cfa12fb424cab29b2 100644
33 --- a/test/test_commit.rb
34 +++ b/test/test_commit.rb
35 @@ -98,18 +98,6 @@ class TestCommit < Test::Unit::TestCase
36 assert_equal true, diffs[5].new_file
37 end
38
39 - def test_diffs_on_initial_import_with_empty_commit
40 - Git.any_instance.expects(:show).with(
41 - {:full_index => true, :pretty => 'raw'},
42 - '634396b2f541a9f2d58b00be1a07f0c358b999b3'
43 - ).returns(fixture('show_empty_commit'))
44 -
45 - @c = Commit.create(@r, :id => '634396b2f541a9f2d58b00be1a07f0c358b999b3')
46 - diffs = @c.diffs
47 -
48 - assert_equal [], diffs
49 - end
50 -
51 # to_s
52
53 def test_to_s
+0
-19
git/test/fixtures/diff_2f less more
0 diff --git a/lib/grit/commit.rb b/lib/grit/commit.rb
1 index a093bb1db8e884cccf396b297259181d1caebed4..80fd3d527f269ecbd570b65b8e21fd85baedb6e9 100644
2 --- a/lib/grit/commit.rb
3 +++ b/lib/grit/commit.rb
4 @@ -156,12 +156,8 @@ module Grit
5
6 def diffs
7 if parents.empty?
8 - diff = @repo.git.show({:full_index => true, :pretty => 'raw'}, @id)
9 - if diff =~ /diff --git a/
10 - diff = diff.sub(/.+?(diff --git a)/m, '\1')
11 - else
12 - diff = ''
13 - end
14 + diff = @repo.git.show({:full_index => true, :pretty => 'raw'}, @id)
15 + diff = diff.sub(/.+?(diff --git a)/m, '\1')
16 Diff.list_from_string(@repo, diff)
17 else
18 self.class.diff(@repo, parents.first.id, @id)
+0
-1
git/test/fixtures/diff_abbrev-40_full-index_M_raw_no-color less more
0 :100644 100644 739bc65220ad90e9ebfa2d6af1723b97555569a4 0000000000000000000000000000000000000000 M README.md
+0
-10
git/test/fixtures/diff_change_in_type less more
0 diff --git a/this b/this
1 deleted file mode 100644
2 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
3 diff --git a/this b/this
4 new file mode 120000
5 index 0000000000000000000000000000000000000000..42061c01a1c70097d1e4579f29a5adf40abdec95
6 --- /dev/null
7 +++ b/this
8 @@ -0,0 +1 @@
9 +that
+0
-1
git/test/fixtures/diff_change_in_type_raw less more
0 :100644 120000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 42061c01a1c70097d1e4579f29a5adf40abdec95 T this
+0
-4
git/test/fixtures/diff_copied_mode less more
0 diff --git a/test1.txt b/test2.txt
1 similarity index 100%
2 copy from test1.txt
3 copy to test2.txt
+0
-1
git/test/fixtures/diff_copied_mode_raw less more
0 :100644 100644 cfe9deac6e10683917e80f877566b58644aa21df cfe9deac6e10683917e80f877566b58644aa21df C100 test1.txt test2.txt
+0
-15
git/test/fixtures/diff_f less more
0 diff --git a/lib/grit/diff.rb b/lib/grit/diff.rb
1 index 537955bb86a8ceaa19aea89e75ccbea5ce6f2698..00b0b4a67eca9242db5f8991e99625acd55f040c 100644
2 --- a/lib/grit/diff.rb
3 +++ b/lib/grit/diff.rb
4 @@ -27,6 +27,10 @@ module Grit
5 while !lines.empty?
6 m, a_path, b_path = *lines.shift.match(%r{^diff --git a/(\S+) b/(\S+)$})
7
8 + if lines.first =~ /^old mode/
9 + 2.times { lines.shift }
10 + end
11 +
12 new_file = false
13 deleted_file = false
14
+0
-7
git/test/fixtures/diff_file_with_spaces less more
0 diff --git a/file with spaces b/file with spaces
1 new file mode 100644
2 index 0000000000000000000000000000000000000000..75c620d7b0d3b0100415421a97f553c979d75174
3 --- /dev/null
4 +++ b/file with spaces
5 @@ -0,0 +1 @@
6 +ohai
+0
-201
git/test/fixtures/diff_i less more
0 commit 634396b2f541a9f2d58b00be1a07f0c358b999b3
1 Author: Tom Preston-Werner <tom@mojombo.com>
2 Date: Tue Oct 9 23:18:20 2007 -0700
3
4 initial grit setup
5
6 diff --git a/History.txt b/History.txt
7 new file mode 100644
8 index 0000000000000000000000000000000000000000..81d2c27608b352814cbe979a6acd678d30219678
9 --- /dev/null
10 +++ b/History.txt
11 @@ -0,0 +1,5 @@
12 +== 1.0.0 / 2007-10-09
13 +
14 +* 1 major enhancement
15 + * Birthday!
16 +
17 diff --git a/Manifest.txt b/Manifest.txt
18 new file mode 100644
19 index 0000000000000000000000000000000000000000..641972d82c6d1b51122274ae8f6a0ecdfb56ee22
20 --- /dev/null
21 +++ b/Manifest.txt
22 @@ -0,0 +1,7 @@
23 +History.txt
24 +Manifest.txt
25 +README.txt
26 +Rakefile
27 +bin/grit
28 +lib/grit.rb
29 +test/test_grit.rb
30 \ No newline at end of file
31 diff --git a/README.txt b/README.txt
32 new file mode 100644
33 index 0000000000000000000000000000000000000000..8b1e02c0fb554eed2ce2ef737a68bb369d7527df
34 --- /dev/null
35 +++ b/README.txt
36 @@ -0,0 +1,48 @@
37 +grit
38 + by FIX (your name)
39 + FIX (url)
40 +
41 +== DESCRIPTION:
42 +
43 +FIX (describe your package)
44 +
45 +== FEATURES/PROBLEMS:
46 +
47 +* FIX (list of features or problems)
48 +
49 +== SYNOPSIS:
50 +
51 + FIX (code sample of usage)
52 +
53 +== REQUIREMENTS:
54 +
55 +* FIX (list of requirements)
56 +
57 +== INSTALL:
58 +
59 +* FIX (sudo gem install, anything else)
60 +
61 +== LICENSE:
62 +
63 +(The MIT License)
64 +
65 +Copyright (c) 2007 FIX
66 +
67 +Permission is hereby granted, free of charge, to any person obtaining
68 +a copy of this software and associated documentation files (the
69 +'Software'), to deal in the Software without restriction, including
70 +without limitation the rights to use, copy, modify, merge, publish,
71 +distribute, sublicense, and/or sell copies of the Software, and to
72 +permit persons to whom the Software is furnished to do so, subject to
73 +the following conditions:
74 +
75 +The above copyright notice and this permission notice shall be
76 +included in all copies or substantial portions of the Software.
77 +
78 +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
79 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
80 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
81 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
82 +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
83 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
84 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
85 diff --git a/Rakefile b/Rakefile
86 new file mode 100644
87 index 0000000000000000000000000000000000000000..ff69c3684a18592c741332b290492aa39d980e02
88 --- /dev/null
89 +++ b/Rakefile
90 @@ -0,0 +1,17 @@
91 +# -*- ruby -*-
92 +
93 +require 'rubygems'
94 +require 'hoe'
95 +require './lib/grit.rb'
96 +
97 +Hoe.new('grit', GitPython.VERSION) do |p|
98 + p.rubyforge_name = 'grit'
99 + # p.author = 'FIX'
100 + # p.email = 'FIX'
101 + # p.summary = 'FIX'
102 + # p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
103 + # p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
104 + p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
105 +end
106 +
107 +# vim: syntax=Ruby
108 diff --git a/bin/grit b/bin/grit
109 new file mode 100644
110 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
111 diff --git a/lib/grit.rb b/lib/grit.rb
112 new file mode 100644
113 index 0000000000000000000000000000000000000000..32cec87d1e78946a827ddf6a8776be4d81dcf1d1
114 --- /dev/null
115 +++ b/lib/grit.rb
116 @@ -0,0 +1,12 @@
117 +$:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
118 +
119 +# core
120 +
121 +# stdlib
122 +
123 +# internal requires
124 +require 'grit/grit'
125 +
126 +class Grit
127 + VERSION = '1.0.0'
128 +end
129 \ No newline at end of file
130 diff --git a/lib/grit/errors.rb b/lib/grit/errors.rb
131 new file mode 100644
132 index 0000000000000000000000000000000000000000..b3be31553741937607a89be8b6a2ab1df208852e
133 --- /dev/null
134 +++ b/lib/grit/errors.rb
135 @@ -0,0 +1,4 @@
136 +class Grit
137 + class InvalidGitRepositoryError < StandardError
138 + end
139 +end
140 \ No newline at end of file
141 diff --git a/lib/grit/grit.rb b/lib/grit/grit.rb
142 new file mode 100644
143 index 0000000000000000000000000000000000000000..48fd36e16081ec09903f7a0e2253b3d16f9efb01
144 --- /dev/null
145 +++ b/lib/grit/grit.rb
146 @@ -0,0 +1,24 @@
147 +class Grit
148 + attr_accessor :path
149 +
150 + # Create a new Grit instance
151 + # +path+ is the path to either the root git directory or the bare git repo
152 + #
153 + # Examples
154 + # g = Grit.new("/Users/tom/dev/grit")
155 + # g = Grit.new("/Users/tom/public/grit.git")
156 + def initialize(path)
157 + if File.exist?(File.join(path, '.git'))
158 + self.path = File.join(path, '.git')
159 + elsif File.exist?(path) && path =~ /\.git$/
160 + self.path = path
161 + else
162 + raise InvalidGitRepositoryError.new(path) unless File.exist?(path)
163 + end
164 + end
165 +
166 + # Return the project's description. Taken verbatim from REPO/description
167 + def description
168 + File.open(File.join(self.path, 'description')).read.chomp
169 + end
170 +end
171 \ No newline at end of file
172 diff --git a/test/helper.rb b/test/helper.rb
173 new file mode 100644
174 index 0000000000000000000000000000000000000000..56e21da6b4ce3021d2754775dfa589947a4e37e5
175 --- /dev/null
176 +++ b/test/helper.rb
177 @@ -0,0 +1,5 @@
178 +require File.join(File.dirname(__FILE__), *%w[.. lib grit])
179 +
180 +require 'test/unit'
181 +
182 +GRIT_REPO = File.join(File.dirname(__FILE__), *%w[..])
183 diff --git a/test/test_grit.rb b/test/test_grit.rb
184 new file mode 100644
185 index 0000000000000000000000000000000000000000..93aa481b37629797df739380306ae689e13f2855
186 --- /dev/null
187 +++ b/test/test_grit.rb
188 @@ -0,0 +1,11 @@
189 +require File.dirname(__FILE__) + '/helper'
190 +
191 +class TestGrit < Test::Unit::TestCase
192 + def setup
193 + @g = Grit.new(GRIT_REPO)
194 + end
195 +
196 + def test_description
197 + assert_equal "Grit is a ruby library for interfacing with git repositories.", @g.description
198 + end
199 +end
200 \ No newline at end of file
+0
-100
git/test/fixtures/diff_index_patch less more
0 diff --git a/etc/sublime-text/git-python.sublime-project b/etc/sublime-text/git-python.sublime-project
1 index 3dab9f6562ecb0408d9ece8dd63cc4461d280113..9c99a2cff7dc918fbbb61cd57d5d98750a1ef6c5 100644
2 --- a/etc/sublime-text/git-python.sublime-project
3 +++ b/etc/sublime-text/git-python.sublime-project
4 @@ -23,7 +23,7 @@
5 ]
6 },
7 // GITDB
8 - ////////
9 + // ////////
10 {
11 "follow_symlinks": true,
12 "path": "../../git/ext/gitdb",
13 @@ -42,8 +42,8 @@
14 ".tox",
15 ]
16 },
17 - // // SMMAP
18 - // ////////
19 + // // // SMMAP
20 + // // ////////
21 {
22 "follow_symlinks": true,
23 "path": "../../git/ext/gitdb/gitdb/ext/smmap",
24 diff --git a/git/diff.py b/git/diff.py
25 index 24e47bad9d79534d3cf474fec4f79e6fef122bb1..c1ad532e0217e293906bcfef43c523d6a8e21568 100644
26 --- a/git/diff.py
27 +++ b/git/diff.py
28 @@ -302,13 +302,21 @@ class Diff(object):
29 diff_header = cls.re_header.match
30 for diff in ('\n' + text).split('\ndiff --git')[1:]:
31 header = diff_header(diff)
32 - assert header is not None, "Failed to parse diff header from " % diff
33 + assert header is not None, "Failed to parse diff header from '%s'" % diff
34
35 a_path, b_path, similarity_index, rename_from, rename_to, \
36 old_mode, new_mode, new_file_mode, deleted_file_mode, \
37 a_blob_id, b_blob_id, b_mode = header.groups()
38 new_file, deleted_file = bool(new_file_mode), bool(deleted_file_mode)
39
40 + # if a_path.startswith('a/'):
41 + # a_path = a_path[2:]
42 + # if b_path.startswith('b/'):
43 + # b_path = b_path[2:]
44 +
45 + for item in (a_path, b_path, a_blob_id, b_blob_id, old_mode, deleted_file_mode, new_mode, new_file_mode, b_mode, new_file, deleted_file, rename_from, rename_to, diff[header.end():]):
46 + print( "####")
47 + print(item)
48 index.append(Diff(repo, a_path, b_path, a_blob_id, b_blob_id,
49 old_mode or deleted_file_mode, new_mode or new_file_mode or b_mode,
50 new_file, deleted_file, rename_from, rename_to, diff[header.end():]))
51 diff --git a/git/ext/gitdb b/git/ext/gitdb
52 index f2233fbf40f3f69309ce5cc714e99fcbdcd33ec3..a88a777df3909a61be97f1a7b1194dad6de25702 160000
53 --- a/git/ext/gitdb
54 +++ b/git/ext/gitdb
55 @@ -1 +1 @@
56 -Subproject commit f2233fbf40f3f69309ce5cc714e99fcbdcd33ec3
57 +Subproject commit a88a777df3909a61be97f1a7b1194dad6de25702-dirty
58 diff --git a/git/test/fixtures/diff_patch_binary b/git/test/fixtures/diff_patch_binary
59 new file mode 100644
60 index 0000000000000000000000000000000000000000..c92ccd6ebc92a871d38ad7cb8a48bcdb1a5dbc33
61 --- /dev/null
62 +++ b/git/test/fixtures/diff_patch_binary
63 @@ -0,0 +1,3 @@
64 +diff --git a/rps b/rps
65 +index f4567df37451b230b1381b1bc9c2bcad76e08a3c..736bd596a36924d30b480942e9475ce0d734fa0d 100755
66 +Binary files a/rps and b/rps differ
67 diff --git a/git/test/fixtures/diff_raw_binary b/git/test/fixtures/diff_raw_binary
68 new file mode 100644
69 index 0000000000000000000000000000000000000000..d4673fa41ee8413384167fc7b9f25e4daf18a53a
70 --- /dev/null
71 +++ b/git/test/fixtures/diff_raw_binary
72 @@ -0,0 +1 @@
73 +:100755 100755 f4567df37451b230b1381b1bc9c2bcad76e08a3c 736bd596a36924d30b480942e9475ce0d734fa0d M rps
74 diff --git a/git/test/test_diff.py b/git/test/test_diff.py
75 index ce0f64f2261bd8de063233108caac1f26742c1fd..4de26f8884fd048ac7f10007f2bf7c7fa3fa60f4 100644
76 --- a/git/test/test_diff.py
77 +++ b/git/test/test_diff.py
78 @@ -65,6 +65,21 @@ class TestDiff(TestBase):
79 assert diff.rename_to == 'that'
80 assert len(list(diffs.iter_change_type('R'))) == 1
81
82 + def test_binary_diff(self):
83 + for method, file_name in ((Diff._index_from_patch_format, 'diff_patch_binary'),
84 + (Diff._index_from_raw_format, 'diff_raw_binary')):
85 + res = method(None, StringProcessAdapter(fixture(file_name)).stdout)
86 + assert len(res) == 1
87 + assert len(list(res.iter_change_type('M'))) == 1
88 + if res[0].diff:
89 + assert res[0].diff == "Binary files a/rps and b/rps differ\n", "in patch mode, we get a diff text"
90 + assert isinstance(str(res[0]), str), "This call should just work"
91 + # end for each method to test
92 +
93 + def test_diff_index(self):
94 + res = self.rorepo.index.diff('17f5d13a7a741dcbb2a30e147bdafe929cff4697', create_patch=True)
95 + assert len(res) == 3
96 +
97 def test_diff_patch_format(self):
98 # test all of the 'old' format diffs for completness - it should at least
99 # be able to deal with it
+0
-1
git/test/fixtures/diff_index_raw less more
0 :100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D
+0
-8
git/test/fixtures/diff_initial less more
0 @@ -0,0 +1,7 @@
1 +=======
2 +CHANGES
3 +=======
4 +
5 +0.1.0
6 +=====
7 +initial release
+0
-1152
git/test/fixtures/diff_mode_only less more
0 diff --git a/bin/merb b/bin/merb
1 old mode 100644
2 new mode 100755
3 diff --git a/lib/merb.rb b/lib/merb.rb
4 index 76cb3e269e46fdf9b63cda7cb563c6cf40fdcb15..a2ab4ed47f9cb2ab942da5c46a2b561758a0d704 100644
5 --- a/lib/merb.rb
6 +++ b/lib/merb.rb
7 @@ -15,7 +15,7 @@ require 'merb_core/core_ext'
8 require 'merb_core/gem_ext/erubis'
9 require 'merb_core/logger'
10 require 'merb_core/version'
11 -
12 +require 'merb_core/controller/mime'
13
14 module Merb
15 class << self
16 @@ -23,6 +23,7 @@ module Merb
17 def start(argv=ARGV)
18 Merb::Config.parse_args(argv)
19 BootLoader.run
20 +
21 case Merb::Config[:adapter]
22 when "mongrel"
23 adapter = Merb::Rack::Mongrel
24 diff --git a/lib/merb_core/boot/bootloader.rb b/lib/merb_core/boot/bootloader.rb
25 index d873924860bf4da06ac93db5c6a188f63dd1c3cc..57da75f05e28e8a256922bf345ccd3902e0a0b02 100644
26 --- a/lib/merb_core/boot/bootloader.rb
27 +++ b/lib/merb_core/boot/bootloader.rb
28 @@ -20,7 +20,7 @@ module Merb
29 end
30
31 def run
32 - subclasses.each {|klass| Object.full_const_get(klass).new.run }
33 + subclasses.each {|klass| Object.full_const_get(klass).run }
34 end
35
36 def after(klass)
37 @@ -37,95 +37,128 @@ module Merb
38
39 end
40
41 -class Merb::BootLoader::BuildFramework < Merb::BootLoader
42 - def run
43 - build_framework
44 +class Merb::BootLoader::LoadInit < Merb::BootLoader
45 + def self.run
46 + if Merb::Config[:init_file]
47 + require Merb.root / Merb::Config[:init_file]
48 + elsif File.exists?(Merb.root / "config" / "merb_init.rb")
49 + require Merb.root / "config" / "merb_init"
50 + elsif File.exists?(Merb.root / "merb_init.rb")
51 + require Merb.root / "merb_init"
52 + elsif File.exists?(Merb.root / "application.rb")
53 + require Merb.root / "application"
54 + end
55 + end
56 +end
57 +
58 +class Merb::BootLoader::Environment < Merb::BootLoader
59 + def self.run
60 + Merb.environment = Merb::Config[:environment]
61 + end
62 +end
63 +
64 +class Merb::BootLoader::Logger < Merb::BootLoader
65 + def self.run
66 + Merb.logger = Merb::Logger.new(Merb.dir_for(:log) / "test_log")
67 + Merb.logger.level = Merb::Logger.const_get(Merb::Config[:log_level].upcase) rescue Merb::Logger::INFO
68 end
69 +end
70 +
71 +class Merb::BootLoader::BuildFramework < Merb::BootLoader
72 + class << self
73 + def run
74 + build_framework
75 + end
76
77 - # This method should be overridden in merb_init.rb before Merb.start to set up a different
78 - # framework structure
79 - def build_framework
80 - %[view model controller helper mailer part].each do |component|
81 - Merb.push_path(component.to_sym, Merb.root_path("app/#{component}s"))
82 + # This method should be overridden in merb_init.rb before Merb.start to set up a different
83 + # framework structure
84 + def build_framework
85 + %w[view model controller helper mailer part].each do |component|
86 + Merb.push_path(component.to_sym, Merb.root_path("app/#{component}s"))
87 + end
88 + Merb.push_path(:application, Merb.root_path("app/controllers/application.rb"))
89 + Merb.push_path(:config, Merb.root_path("config/router.rb"))
90 + Merb.push_path(:lib, Merb.root_path("lib"))
91 end
92 - Merb.push_path(:application, Merb.root_path("app/controllers/application.rb"))
93 - Merb.push_path(:config, Merb.root_path("config/router.rb"))
94 - Merb.push_path(:lib, Merb.root_path("lib"))
95 end
96 end
97
98 class Merb::BootLoader::LoadPaths < Merb::BootLoader
99 LOADED_CLASSES = {}
100
101 - def run
102 - # Add models, controllers, and lib to the load path
103 - $LOAD_PATH.unshift Merb.load_paths[:model].first if Merb.load_paths[:model]
104 - $LOAD_PATH.unshift Merb.load_paths[:controller].first if Merb.load_paths[:controller]
105 - $LOAD_PATH.unshift Merb.load_paths[:lib].first if Merb.load_paths[:lib]
106 + class << self
107 + def run
108 + # Add models, controllers, and lib to the load path
109 + $LOAD_PATH.unshift Merb.load_paths[:model].first if Merb.load_paths[:model]
110 + $LOAD_PATH.unshift Merb.load_paths[:controller].first if Merb.load_paths[:controller]
111 + $LOAD_PATH.unshift Merb.load_paths[:lib].first if Merb.load_paths[:lib]
112
113 - # Require all the files in the registered load paths
114 - puts Merb.load_paths.inspect
115 - Merb.load_paths.each do |name, path|
116 - Dir[path.first / path.last].each do |file|
117 - klasses = ObjectSpace.classes.dup
118 - require f
119 - LOADED_CLASSES[file] = ObjectSpace.classes - klasses
120 + # Require all the files in the registered load paths
121 + puts Merb.load_paths.inspect
122 + Merb.load_paths.each do |name, path|
123 + Dir[path.first / path.last].each do |file|
124 + klasses = ObjectSpace.classes.dup
125 + require file
126 + LOADED_CLASSES[file] = ObjectSpace.classes - klasses
127 + end
128 end
129 end
130 - end
131
132 - def reload(file)
133 - if klasses = LOADED_CLASSES[file]
134 - klasses.each do |klass|
135 - remove_constant(klass)
136 + def reload(file)
137 + if klasses = LOADED_CLASSES[file]
138 + klasses.each do |klass|
139 + remove_constant(klass)
140 + end
141 end
142 + load file
143 end
144 - load file
145 - end
146
147 - def remove_constant(const)
148 - # This is to support superclasses (like AbstractController) that track
149 - # their subclasses in a class variable. Classes that wish to use this
150 - # functionality are required to alias it to _subclasses_list. Plugins
151 - # for ORMs and other libraries should keep this in mind.
152 - if klass.superclass.respond_to?(:_subclasses_list)
153 - klass.superclass.send(:_subclasses_list).delete(klass)
154 - klass.superclass.send(:_subclasses_list).delete(klass.to_s)
155 - end
156 + def remove_constant(const)
157 + # This is to support superclasses (like AbstractController) that track
158 + # their subclasses in a class variable. Classes that wish to use this
159 + # functionality are required to alias it to _subclasses_list. Plugins
160 + # for ORMs and other libraries should keep this in mind.
161 + if klass.superclass.respond_to?(:_subclasses_list)
162 + klass.superclass.send(:_subclasses_list).delete(klass)
163 + klass.superclass.send(:_subclasses_list).delete(klass.to_s)
164 + end
165
166 - parts = const.to_s.split("::")
167 - base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::"))
168 - object = parts[-1].intern
169 - Merb.logger.debugger("Removing constant #{object} from #{base}")
170 - base.send(:remove_const, object) if object
171 + parts = const.to_s.split("::")
172 + base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::"))
173 + object = parts[-1].intern
174 + Merb.logger.debugger("Removing constant #{object} from #{base}")
175 + base.send(:remove_const, object) if object
176 + end
177 end
178
179 end
180
181 class Merb::BootLoader::Templates < Merb::BootLoader
182 - def run
183 - template_paths.each do |path|
184 - Merb::Template.inline_template(path)
185 + class << self
186 + def run
187 + template_paths.each do |path|
188 + Merb::Template.inline_template(path)
189 + end
190 end
191 - end
192
193 - def template_paths
194 - extension_glob = "{#{Merb::Template::EXTENSIONS.keys.join(',')}}"
195 + def template_paths
196 + extension_glob = "{#{Merb::Template::EXTENSIONS.keys.join(',')}}"
197
198 - # This gets all templates set in the controllers template roots
199 - # We separate the two maps because most of controllers will have
200 - # the same _template_root, so it's silly to be globbing the same
201 - # path over and over.
202 - template_paths = Merb::AbstractController._abstract_subclasses.map do |klass|
203 - Object.full_const_get(klass)._template_root
204 - end.uniq.map {|path| Dir["#{path}/**/*.#{extension_glob}"] }
205 + # This gets all templates set in the controllers template roots
206 + # We separate the two maps because most of controllers will have
207 + # the same _template_root, so it's silly to be globbing the same
208 + # path over and over.
209 + template_paths = Merb::AbstractController._abstract_subclasses.map do |klass|
210 + Object.full_const_get(klass)._template_root
211 + end.uniq.compact.map {|path| Dir["#{path}/**/*.#{extension_glob}"] }
212
213 - # This gets the templates that might be created outside controllers
214 - # template roots. eg app/views/shared/*
215 - template_paths << Dir["#{Merb.dir_for(:view)}/**/*.#{extension_glob}"] if Merb.dir_for(:view)
216 + # This gets the templates that might be created outside controllers
217 + # template roots. eg app/views/shared/*
218 + template_paths << Dir["#{Merb.dir_for(:view)}/**/*.#{extension_glob}"] if Merb.dir_for(:view)
219
220 - template_paths.flatten.compact.uniq
221 - end
222 + template_paths.flatten.compact.uniq
223 + end
224 + end
225 end
226
227 class Merb::BootLoader::Libraries < Merb::BootLoader
228 @@ -145,18 +178,41 @@ class Merb::BootLoader::Libraries < Merb::BootLoader
229 def self.add_libraries(hsh)
230 @@libraries.merge!(hsh)
231 end
232 -
233 - def run
234 +
235 + def self.run
236 @@libraries.each do |exclude, choices|
237 require_first_working(*choices) unless Merb::Config[exclude]
238 end
239 end
240 -
241 - def require_first_working(first, *rest)
242 +
243 + def self.require_first_working(first, *rest)
244 p first, rest
245 require first
246 rescue LoadError
247 raise LoadError if rest.empty?
248 require_first_working rest.unshift, *rest
249 end
250 +end
251 +
252 +class Merb::BootLoader::MimeTypes < Merb::BootLoader
253 + def self.run
254 + # Sets the default mime-types
255 + #
256 + # By default, the mime-types include:
257 + # :all:: no transform, */*
258 + # :yaml:: to_yaml, application/x-yaml or text/yaml
259 + # :text:: to_text, text/plain
260 + # :html:: to_html, text/html or application/xhtml+xml or application/html
261 + # :xml:: to_xml, application/xml or text/xml or application/x-xml, adds "Encoding: UTF-8" response header
262 + # :js:: to_json, text/javascript ot application/javascript or application/x-javascript
263 + # :json:: to_json, application/json or text/x-json
264 + Merb.available_mime_types.clear
265 + Merb.add_mime_type(:all, nil, %w[*/*])
266 + Merb.add_mime_type(:yaml, :to_yaml, %w[application/x-yaml text/yaml])
267 + Merb.add_mime_type(:text, :to_text, %w[text/plain])
268 + Merb.add_mime_type(:html, :to_html, %w[text/html application/xhtml+xml application/html])
269 + Merb.add_mime_type(:xml, :to_xml, %w[application/xml text/xml application/x-xml], :Encoding => "UTF-8")
270 + Merb.add_mime_type(:js, :to_json, %w[text/javascript application/javascript application/x-javascript])
271 + Merb.add_mime_type(:json, :to_json, %w[application/json text/x-json])
272 + end
273 end
274 \ No newline at end of file
275 diff --git a/lib/merb_core/config.rb b/lib/merb_core/config.rb
276 index c92f2e6f071c234551ecb16a4716d47fa92f6c7b..ab0864e0174b54833c758f9f22a840d3b53c7653 100644
277 --- a/lib/merb_core/config.rb
278 +++ b/lib/merb_core/config.rb
279 @@ -92,6 +92,10 @@ module Merb
280 options[:cluster] = nodes
281 end
282
283 + opts.on("-I", "--init-file FILE", "Name of the file to load first") do |init_file|
284 + options[:init_file] = init_file
285 + end
286 +
287 opts.on("-p", "--port PORTNUM", "Port to run merb on, defaults to 4000.") do |port|
288 options[:port] = port
289 end
290 @@ -261,29 +265,29 @@ module Merb
291
292 @configuration = Merb::Config.apply_configuration_from_file options, environment_merb_yml
293
294 - case Merb::Config[:environment].to_s
295 - when 'production'
296 - Merb::Config[:reloader] = Merb::Config.fetch(:reloader, false)
297 - Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, false)
298 - Merb::Config[:cache_templates] = true
299 - else
300 - Merb::Config[:reloader] = Merb::Config.fetch(:reloader, true)
301 - Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, true)
302 - end
303 -
304 - Merb::Config[:reloader_time] ||= 0.5 if Merb::Config[:reloader] == true
305 -
306 -
307 - if Merb::Config[:reloader]
308 - Thread.abort_on_exception = true
309 - Thread.new do
310 - loop do
311 - sleep( Merb::Config[:reloader_time] )
312 - ::Merb::BootLoader.reload if ::Merb::BootLoader.app_loaded?
313 - end
314 - Thread.exit
315 - end
316 - end
317 + # case Merb::Config[:environment].to_s
318 + # when 'production'
319 + # Merb::Config[:reloader] = Merb::Config.fetch(:reloader, false)
320 + # Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, false)
321 + # Merb::Config[:cache_templates] = true
322 + # else
323 + # Merb::Config[:reloader] = Merb::Config.fetch(:reloader, true)
324 + # Merb::Config[:exception_details] = Merb::Config.fetch(:exception_details, true)
325 + # end
326 + #
327 + # Merb::Config[:reloader_time] ||= 0.5 if Merb::Config[:reloader] == true
328 + #
329 + #
330 + # if Merb::Config[:reloader]
331 + # Thread.abort_on_exception = true
332 + # Thread.new do
333 + # loop do
334 + # sleep( Merb::Config[:reloader_time] )
335 + # ::Merb::BootLoader.reload if ::Merb::BootLoader.app_loaded?
336 + # end
337 + # Thread.exit
338 + # end
339 + # end
340 @configuration
341 end
342
343 diff --git a/lib/merb_core/controller/abstract_controller.rb b/lib/merb_core/controller/abstract_controller.rb
344 index fbf83372793da6da4b803b799994f0e341fddf88..f5e9a59057d67a6d56377a516a726cf51aa03d6f 100644
345 --- a/lib/merb_core/controller/abstract_controller.rb
346 +++ b/lib/merb_core/controller/abstract_controller.rb
347 @@ -96,7 +96,7 @@ class Merb::AbstractController
348 # the superclass.
349 #---
350 # @public
351 - def _template_location(action, controller = controller_name, type = nil)
352 + def _template_location(action, type = nil, controller = controller_name)
353 "#{controller}/#{action}"
354 end
355
356 @@ -106,6 +106,8 @@ class Merb::AbstractController
357 # own subclasses. We're using a Set so we don't have to worry about
358 # uniqueness.
359 self._abstract_subclasses = Set.new
360 + self._template_root = Merb.dir_for(:view)
361 +
362 def self.subclasses_list() _abstract_subclasses end
363
364 class << self
365 @@ -114,7 +116,6 @@ class Merb::AbstractController
366 # The controller that is being inherited from Merb::AbstractController
367 def inherited(klass)
368 _abstract_subclasses << klass.to_s
369 - klass._template_root ||= Merb.dir_for(:view)
370 super
371 end
372
373 diff --git a/lib/merb_core/controller/merb_controller.rb b/lib/merb_core/controller/merb_controller.rb
374 index 7283f006bb0501b29f825da129600cf045264b62..98af6ef3330a6b3f46d7bb1f8643261e28155ae5 100644
375 --- a/lib/merb_core/controller/merb_controller.rb
376 +++ b/lib/merb_core/controller/merb_controller.rb
377 @@ -71,6 +71,10 @@ class Merb::Controller < Merb::AbstractController
378 end
379 end
380
381 + def _template_location(action, type = nil, controller = controller_name)
382 + "#{controller}/#{action}.#{type}"
383 + end
384 +
385 # Sets the variables that came in through the dispatch as available to
386 # the controller. This is called by .build, so see it for more
387 # information.
388 @@ -107,9 +111,7 @@ class Merb::Controller < Merb::AbstractController
389 request.cookies[_session_id_key] = request.params[_session_id_key]
390 end
391 end
392 - @_request, @_response, @_status, @_headers =
393 - request, response, status, headers
394 -
395 + @request, @response, @status, @headers = request, response, status, headers
396 nil
397 end
398
399 @@ -135,7 +137,8 @@ class Merb::Controller < Merb::AbstractController
400 @_benchmarks[:action_time] = Time.now - start
401 end
402
403 - _attr_reader :request, :response, :status, :headers
404 + attr_reader :request, :response, :headers
405 + attr_accessor :status
406 def params() request.params end
407 def cookies() request.cookies end
408 def session() request.session end
409 diff --git a/lib/merb_core/controller/mime.rb b/lib/merb_core/controller/mime.rb
410 index d17570786ca318cff7201c4b1e947ae229b01de8..ff9abe4d1c452aeabfcf5f7dc7a2c7cdd3f67035 100644
411 --- a/lib/merb_core/controller/mime.rb
412 +++ b/lib/merb_core/controller/mime.rb
413 @@ -8,7 +8,7 @@ module Merb
414
415 # Any specific outgoing headers should be included here. These are not
416 # the content-type header but anything in addition to it.
417 - # +tranform_method+ should be set to a symbol of the method used to
418 + # +transform_method+ should be set to a symbol of the method used to
419 # transform a resource into this mime type.
420 # For example for the :xml mime type an object might be transformed by
421 # calling :to_xml, or for the :js mime type, :to_json.
422 @@ -71,27 +71,6 @@ module Merb
423 def mime_by_request_header(header)
424 available_mime_types.find {|key,info| info[request_headers].include?(header)}.first
425 end
426 -
427 - # Resets the default mime-types
428 - #
429 - # By default, the mime-types include:
430 - # :all:: no transform, */*
431 - # :yaml:: to_yaml, application/x-yaml or text/yaml
432 - # :text:: to_text, text/plain
433 - # :html:: to_html, text/html or application/xhtml+xml or application/html
434 - # :xml:: to_xml, application/xml or text/xml or application/x-xml, adds "Encoding: UTF-8" response header
435 - # :js:: to_json, text/javascript ot application/javascript or application/x-javascript
436 - # :json:: to_json, application/json or text/x-json
437 - def reset_default_mime_types!
438 - available_mime_types.clear
439 - Merb.add_mime_type(:all, nil, %w[*/*])
440 - Merb.add_mime_type(:yaml, :to_yaml, %w[application/x-yaml text/yaml])
441 - Merb.add_mime_type(:text, :to_text, %w[text/plain])
442 - Merb.add_mime_type(:html, :to_html, %w[text/html application/xhtml+xml application/html])
443 - Merb.add_mime_type(:xml, :to_xml, %w[application/xml text/xml application/x-xml], :Encoding => "UTF-8")
444 - Merb.add_mime_type(:js, :to_json, %w[text/javascript application/javascript application/x-javascript])
445 - Merb.add_mime_type(:json, :to_json, %w[application/json text/x-json])
446 - end
447
448 end
449 end
450 \ No newline at end of file
451 diff --git a/lib/merb_core/controller/mixins/render.rb b/lib/merb_core/controller/mixins/render.rb
452 index 8e096546d4647bb597ab2e00a4b15d09db35e9c9..a298263af7d655d9ce43007554f3827046831287 100644
453 --- a/lib/merb_core/controller/mixins/render.rb
454 +++ b/lib/merb_core/controller/mixins/render.rb
455 @@ -51,21 +51,22 @@ module Merb::RenderMixin
456
457 # If you don't specify a thing to render, assume they want to render the current action
458 thing ||= action_name.to_sym
459 -
460 +
461 # Content negotiation
462 opts[:format] ? (self.content_type = opts[:format]) : content_type
463
464 # Do we have a template to try to render?
465 if thing.is_a?(Symbol) || opts[:template]
466 -
467 +
468 # Find a template path to look up (_template_location adds flexibility here)
469 - template_location = _template_root / (opts[:template] || _template_location(thing))
470 + template_location = _template_root / (opts[:template] || _template_location(thing, content_type))
471 +
472 # Get the method name from the previously inlined list
473 template_method = Merb::Template.template_for(template_location)
474
475 # Raise an error if there's no template
476 raise TemplateNotFound, "No template found at #{template_location}" unless
477 - self.respond_to?(template_method)
478 + template_method && self.respond_to?(template_method)
479
480 # Call the method in question and throw the content for later consumption by the layout
481 throw_content(:for_layout, self.send(template_method))
482 diff --git a/lib/merb_core/controller/mixins/responder.rb b/lib/merb_core/controller/mixins/responder.rb
483 index e910b2b32c844ab51cf2a10d0ad26c314dbb3631..5ac67fb907aaf9f95effc7eb3cbb07b8963ce022 100644
484 --- a/lib/merb_core/controller/mixins/responder.rb
485 +++ b/lib/merb_core/controller/mixins/responder.rb
486 @@ -97,6 +97,8 @@ module Merb
487 # and none of the provides methods can be used.
488 module ResponderMixin
489
490 + TYPES = {}
491 +
492 class ContentTypeAlreadySet < StandardError; end
493
494 # ==== Parameters
495 @@ -105,6 +107,7 @@ module Merb
496 base.extend(ClassMethods)
497 base.class_eval do
498 class_inheritable_accessor :class_provided_formats
499 + self.class_provided_formats = []
500 end
501 base.reset_provides
502 end
503 @@ -178,171 +181,253 @@ module Merb
504 def reset_provides
505 only_provides(:html)
506 end
507 -
508 - # ==== Returns
509 - # The current list of formats provided for this instance of the controller.
510 - # It starts with what has been set in the controller (or :html by default)
511 - # but can be modifed on a per-action basis.
512 - def _provided_formats
513 - @_provided_formats ||= class_provided_formats.dup
514 + end
515 +
516 + # ==== Returns
517 + # The current list of formats provided for this instance of the controller.
518 + # It starts with what has been set in the controller (or :html by default)
519 + # but can be modifed on a per-action basis.
520 + def _provided_formats
521 + @_provided_formats ||= class_provided_formats.dup
522 + end
523 +
524 + # Sets the provided formats for this action. Usually, you would
525 + # use a combination of +provides+, +only_provides+ and +does_not_provide+
526 + # to manage this, but you can set it directly.
527 + #
528 + # ==== Parameters
529 + # *formats<Symbol>:: A list of formats to be passed to provides
530 + #
531 + # ==== Raises
532 + # Merb::ResponderMixin::ContentTypeAlreadySet::
533 + # Content negotiation already occured, and the content_type is set.
534 + #
535 + # ==== Returns
536 + # Array:: List of formats passed in
537 + def _set_provided_formats(*formats)
538 + if @_content_type
539 + raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
540 end
541 -
542 - # Sets the provided formats for this action. Usually, you would
543 - # use a combination of +provides+, +only_provides+ and +does_not_provide+
544 - # to manage this, but you can set it directly.
545 - #
546 - # ==== Parameters
547 - # *formats<Symbol>:: A list of formats to be passed to provides
548 - #
549 - # ==== Raises
550 - # Merb::ResponderMixin::ContentTypeAlreadySet::
551 - # Content negotiation already occured, and the content_type is set.
552 - #
553 - # ==== Returns
554 - # Array:: List of formats passed in
555 - def _set_provided_formats(*formats)
556 - if @_content_type
557 - raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
558 - end
559 - @_provided_formats = []
560 - provides(*formats)
561 + @_provided_formats = []
562 + provides(*formats)
563 + end
564 + alias :_provided_formats= :_set_provided_formats
565 +
566 + # Adds formats to the list of provided formats for this particular
567 + # request. Usually used to add formats to a single action. See also
568 + # the controller-level provides that affects all actions in a controller.
569 + #
570 + # ==== Parameters
571 + # *formats<Symbol>:: A list of formats to add to the per-action list
572 + # of provided formats
573 + #
574 + # ==== Raises
575 + # Merb::ResponderMixin::ContentTypeAlreadySet::
576 + # Content negotiation already occured, and the content_type is set.
577 + #
578 + # ==== Returns
579 + # Array:: List of formats passed in
580 + #
581 + #---
582 + # @public
583 + def provides(*formats)
584 + if @_content_type
585 + raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
586 end
587 - alias :_provided_formats= :_set_provided_formats
588 -
589 - # Adds formats to the list of provided formats for this particular
590 - # request. Usually used to add formats to a single action. See also
591 - # the controller-level provides that affects all actions in a controller.
592 - #
593 - # ==== Parameters
594 - # *formats<Symbol>:: A list of formats to add to the per-action list
595 - # of provided formats
596 - #
597 - # ==== Raises
598 - # Merb::ResponderMixin::ContentTypeAlreadySet::
599 - # Content negotiation already occured, and the content_type is set.
600 - #
601 - # ==== Returns
602 - # Array:: List of formats passed in
603 - #
604 - #---
605 - # @public
606 - def provides(*formats)
607 - if @_content_type
608 - raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
609 - end
610 - formats.each do |fmt|
611 - _provided_formats << fmt unless _provided_formats.include?(fmt)
612 - end
613 + formats.each do |fmt|
614 + _provided_formats << fmt unless _provided_formats.include?(fmt)
615 end
616 + end
617
618 - # Sets list of provided formats for this particular
619 - # request. Usually used to limit formats to a single action. See also
620 - # the controller-level only_provides that affects all actions
621 - # in a controller.
622 - #
623 - # ==== Parameters
624 - # *formats<Symbol>:: A list of formats to use as the per-action list
625 - # of provided formats
626 - #
627 - # ==== Returns
628 - # Array:: List of formats passed in
629 - #
630 - #---
631 - # @public
632 - def only_provides(*formats)
633 - self._provided_formats = *formats
634 - end
635 -
636 - # Removes formats from the list of provided formats for this particular
637 - # request. Usually used to remove formats from a single action. See
638 - # also the controller-level does_not_provide that affects all actions in a
639 - # controller.
640 - #
641 - # ==== Parameters
642 - # *formats<Symbol>:: Registered mime-type
643 - #
644 - # ==== Returns
645 - # Array:: List of formats that remain after removing the ones not to provide
646 - #
647 - #---
648 - # @public
649 - def does_not_provide(*formats)
650 - formats.flatten!
651 - self._provided_formats -= formats
652 - end
653 -
654 - # Do the content negotiation:
655 - # 1. if params[:format] is there, and provided, use it
656 - # 2. Parse the Accept header
657 - # 3. If it's */*, use the first provided format
658 - # 4. Look for one that is provided, in order of request
659 - # 5. Raise 406 if none found
660 - def _perform_content_negotiation # :nodoc:
661 - raise Merb::ControllerExceptions::NotAcceptable if provided_formats.empty?
662 - if fmt = params[:format]
663 - return fmt.to_sym if provided_formats.include?(fmt.to_sym)
664 - else
665 - accepts = Responder.parse(request.accept).map {|t| t.to_sym}
666 - return provided_formats.first if accepts.include?(:all)
667 - return accepts.each { |type| break type if provided_formats.include?(type) }
668 - end
669 - raise Merb::ControllerExceptions::NotAcceptable
670 + # Sets list of provided formats for this particular
671 + # request. Usually used to limit formats to a single action. See also
672 + # the controller-level only_provides that affects all actions
673 + # in a controller.
674 + #
675 + # ==== Parameters
676 + # *formats<Symbol>:: A list of formats to use as the per-action list
677 + # of provided formats
678 + #
679 + # ==== Returns
680 + # Array:: List of formats passed in
681 + #
682 + #---
683 + # @public
684 + def only_provides(*formats)
685 + self._provided_formats = *formats
686 + end
687 +
688 + # Removes formats from the list of provided formats for this particular
689 + # request. Usually used to remove formats from a single action. See
690 + # also the controller-level does_not_provide that affects all actions in a
691 + # controller.
692 + #
693 + # ==== Parameters
694 + # *formats<Symbol>:: Registered mime-type
695 + #
696 + # ==== Returns
697 + # Array:: List of formats that remain after removing the ones not to provide
698 + #
699 + #---
700 + # @public
701 + def does_not_provide(*formats)
702 + formats.flatten!
703 + self._provided_formats -= formats
704 + end
705 +
706 + # Do the content negotiation:
707 + # 1. if params[:format] is there, and provided, use it
708 + # 2. Parse the Accept header
709 + # 3. If it's */*, use the first provided format
710 + # 4. Look for one that is provided, in order of request
711 + # 5. Raise 406 if none found
712 + def _perform_content_negotiation # :nodoc:
713 + raise Merb::ControllerExceptions::NotAcceptable if _provided_formats.empty?
714 + if fmt = params[:format] && _provided_formats.include?(fmt.to_sym)
715 + return fmt.to_sym
716 end
717 + accepts = Responder.parse(request.accept).map {|t| t.to_sym}
718 + return _provided_formats.first if accepts.include?(:all)
719 + (accepts & _provided_formats).first || (raise Merb::ControllerExceptions::NotAcceptable)
720 + end
721
722 - # Returns the output format for this request, based on the
723 - # provided formats, <tt>params[:format]</tt> and the client's HTTP
724 - # Accept header.
725 - #
726 - # The first time this is called, it triggers content negotiation
727 - # and caches the value. Once you call +content_type+ you can
728 - # not set or change the list of provided formats.
729 - #
730 - # Called automatically by +render+, so you should only call it if
731 - # you need the value, not to trigger content negotiation.
732 - #
733 - # ==== Parameters
734 - # fmt<String?>::
735 - # An optional format to use instead of performing content negotiation.
736 - # This can be used to pass in the values of opts[:format] from the
737 - # render function to short-circuit content-negotiation when it's not
738 - # necessary. This optional parameter should not be considered part
739 - # of the public API.
740 - #
741 - # ==== Returns
742 - # Symbol:: The content-type that will be used for this controller.
743 - #
744 - #---
745 - # @public
746 - def content_type(fmt = nil)
747 - self.content_type = (fmt || _perform_content_negotiation) unless @_content_type
748 - @_content_type
749 + # Returns the output format for this request, based on the
750 + # provided formats, <tt>params[:format]</tt> and the client's HTTP
751 + # Accept header.
752 + #
753 + # The first time this is called, it triggers content negotiation
754 + # and caches the value. Once you call +content_type+ you can
755 + # not set or change the list of provided formats.
756 + #
757 + # Called automatically by +render+, so you should only call it if
758 + # you need the value, not to trigger content negotiation.
759 + #
760 + # ==== Parameters
761 + # fmt<String?>::
762 + # An optional format to use instead of performing content negotiation.
763 + # This can be used to pass in the values of opts[:format] from the
764 + # render function to short-circuit content-negotiation when it's not
765 + # necessary. This optional parameter should not be considered part
766 + # of the public API.
767 + #
768 + # ==== Returns
769 + # Symbol:: The content-type that will be used for this controller.
770 + #
771 + #---
772 + # @public
773 + def content_type(fmt = nil)
774 + @_content_type = (fmt || _perform_content_negotiation) unless @_content_type
775 + @_content_type
776 + end
777 +
778 + # Sets the content type of the current response to a value based on
779 + # a passed in key. The Content-Type header will be set to the first
780 + # registered header for the mime-type.
781 + #
782 + # ==== Parameters
783 + # type<Symbol>:: A type that is in the list of registered mime-types.
784 + #
785 + # ==== Raises
786 + # ArgumentError:: "type" is not in the list of registered mime-types.
787 + #
788 + # ==== Returns
789 + # Symbol:: The content-type that was passed in.
790 + #
791 + #---
792 + # @semipublic
793 + def content_type=(type)
794 + unless Merb.available_mime_types.has_key?(type)
795 + raise Merb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{type}")
796 + end
797 + headers['Content-Type'] = Merb.available_mime_types[type].first
798 + @_content_type = type
799 + end
800 +
801 + end
802 +
803 + class Responder
804 +
805 + protected
806 + def self.parse(accept_header)
807 + # parse the raw accept header into a unique, sorted array of AcceptType objects
808 + list = accept_header.to_s.split(/,/).enum_for(:each_with_index).map do |entry,index|
809 + AcceptType.new(entry,index += 1)
810 + end.sort.uniq
811 + # firefox (and possibly other browsers) send broken default accept headers.
812 + # fix them up by sorting alternate xml forms (namely application/xhtml+xml)
813 + # ahead of pure xml types (application/xml,text/xml).
814 + if app_xml = list.detect{|e| e.super_range == 'application/xml'}
815 + list.select{|e| e.to_s =~ /\+xml/}.each { |acc_type|
816 + list[list.index(acc_type)],list[list.index(app_xml)] =
817 + list[list.index(app_xml)],list[list.index(acc_type)] }
818 end
819 -
820 - # Sets the content type of the current response to a value based on
821 - # a passed in key. The Content-Type header will be set to the first
822 - # registered header for the mime-type.
823 - #
824 - # ==== Parameters
825 - # type<Symbol>:: A type that is in the list of registered mime-types.
826 - #
827 - # ==== Raises
828 - # ArgumentError:: "type" is not in the list of registered mime-types.
829 - #
830 - # ==== Returns
831 - # Symbol:: The content-type that was passed in.
832 - #
833 - #---
834 - # @semipublic
835 - def content_type=(type)
836 - unless Merb.available_mime_types.has_key?(type)
837 - raise Merb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{type}")
838 - end
839 - headers['Content-Type'] = Merb.available_mime_types[type].first
840 - @_content_type = type
841 + list
842 + end
843 +
844 + public
845 + def self.params_to_query_string(value, prefix = nil)
846 + case value
847 + when Array
848 + value.map { |v|
849 + params_to_query_string(v, "#{prefix}[]")
850 + } * "&"
851 + when Hash
852 + value.map { |k, v|
853 + params_to_query_string(v, prefix ? "#{prefix}[#{Merb::Request.escape(k)}]" : Merb::Request.escape(k))
854 + } * "&"
855 + else
856 + "#{prefix}=#{Merb::Request.escape(value)}"
857 end
858 + end
859
860 - end
861 + end
862 +
863 + class AcceptType
864 +
865 + attr_reader :media_range, :quality, :index, :type, :sub_type
866
867 + def initialize(entry,index)
868 + @index = index
869 + @media_range, quality = entry.split(/;\s*q=/).map{|a| a.strip }
870 + @type, @sub_type = @media_range.split(/\//)
871 + quality ||= 0.0 if @media_range == '*/*'
872 + @quality = ((quality || 1.0).to_f * 100).to_i
873 + end
874 +
875 + def <=>(entry)
876 + c = entry.quality <=> quality
877 + c = index <=> entry.index if c == 0
878 + c
879 + end
880 +
881 + def eql?(entry)
882 + synonyms.include?(entry.media_range)
883 + end
884 +
885 + def ==(entry); eql?(entry); end
886 +
887 + def hash; super_range.hash; end
888 +
889 + def synonyms
890 + @syns ||= Merb.available_mime_types.values.map do |e|
891 + e[:request_headers] if e[:request_headers].include?(@media_range)
892 + end.compact.flatten
893 + end
894 +
895 + def super_range
896 + synonyms.first || @media_range
897 + end
898 +
899 + def to_sym
900 + Merb.available_mime_types.select{|k,v|
901 + v[:request_headers] == synonyms || v[:request_headers][0] == synonyms[0]}.flatten.first
902 + end
903 +
904 + def to_s
905 + @media_range
906 + end
907 +
908 end
909 +
910
911 end
912 \ No newline at end of file
913 diff --git a/lib/merb_core/dispatch/dispatcher.rb b/lib/merb_core/dispatch/dispatcher.rb
914 index c458c9f9ad454d3b0c3055d6b2a8e88b17712b44..f7fed0f539a20f9cce08b72c551725ad0563bf37 100644
915 --- a/lib/merb_core/dispatch/dispatcher.rb
916 +++ b/lib/merb_core/dispatch/dispatcher.rb
917 @@ -33,10 +33,10 @@ class Merb::Dispatcher
918
919 # this is the custom dispatch_exception; it allows failures to still be dispatched
920 # to the error controller
921 - rescue => exception
922 - Merb.logger.error(Merb.exception(exception))
923 - exception = controller_exception(exception)
924 - dispatch_exception(request, response, exception)
925 + # rescue => exception
926 + # Merb.logger.error(Merb.exception(exception))
927 + # exception = controller_exception(exception)
928 + # dispatch_exception(request, response, exception)
929 end
930
931 private
932 @@ -49,10 +49,10 @@ class Merb::Dispatcher
933 def dispatch_action(klass, action, request, response, status=200)
934 # build controller
935 controller = klass.build(request, response, status)
936 - if @@use_mutex
937 - @@mutex.synchronize { controller.dispatch(action) }
938 + if use_mutex
939 + @@mutex.synchronize { controller._dispatch(action) }
940 else
941 - controller.dispatch(action)
942 + controller._dispatch(action)
943 end
944 [controller, action]
945 end
946 diff --git a/lib/merb_core/rack/adapter.rb b/lib/merb_core/rack/adapter.rb
947 index ffc7117e9733e83b0567bbe4a43fac7663800b7d..217399a5382d0b3878aaea3d3e302173c5b5f119 100644
948 --- a/lib/merb_core/rack/adapter.rb
949 +++ b/lib/merb_core/rack/adapter.rb
950 @@ -40,7 +40,7 @@ module Merb
951 begin
952 controller, action = ::Merb::Dispatcher.handle(request, response)
953 rescue Object => e
954 - return [500, {"Content-Type"=>"text/html"}, "Internal Server Error"]
955 + return [500, {"Content-Type"=>"text/html"}, e.message + "<br/>" + e.backtrace.join("<br/>")]
956 end
957 [controller.status, controller.headers, controller.body]
958 end
959 diff --git a/lib/merb_core/test/request_helper.rb b/lib/merb_core/test/request_helper.rb
960 index 10a9fb3ace56eaf1db0fa300df3fb2ab88a7118a..f302a3b71539182ba142cd208fe6d6aae171b1a1 100644
961 --- a/lib/merb_core/test/request_helper.rb
962 +++ b/lib/merb_core/test/request_helper.rb
963 @@ -26,8 +26,10 @@ module Merb::Test::RequestHelper
964 Merb::Test::FakeRequest.new(env, StringIO.new(req))
965 end
966
967 - def dispatch_to(controller_klass, action, env = {}, opt = {}, &blk)
968 - request = fake_request(env, opt)
969 + def dispatch_to(controller_klass, action, params = {}, env = {}, &blk)
970 + request = fake_request(env,
971 + :query_string => Merb::Responder.params_to_query_string(params))
972 +
973 controller = controller_klass.build(request)
974 controller.instance_eval(&blk) if block_given?
975 controller._dispatch(action)
976 diff --git a/spec/public/abstract_controller/spec_helper.rb b/spec/public/abstract_controller/spec_helper.rb
977 index df759008d14e7572b5c44de24f77f828f83f1682..694cee2592a210a5c1fa40ca7846beeaa09725fe 100644
978 --- a/spec/public/abstract_controller/spec_helper.rb
979 +++ b/spec/public/abstract_controller/spec_helper.rb
980 @@ -1,12 +1,10 @@
981 __DIR__ = File.dirname(__FILE__)
982 require File.join(__DIR__, "..", "..", "spec_helper")
983
984 -# The framework structure *must* be set up before loading in framework
985 -# files.
986 require File.join(__DIR__, "controllers", "filters")
987 require File.join(__DIR__, "controllers", "render")
988
989 -Merb::BootLoader::Templates.new.run
990 +Merb::BootLoader::Templates.run
991
992 module Merb::Test::Behaviors
993 def dispatch_should_make_body(klass, body, action = :index)
994 diff --git a/spec/public/controller/base_spec.rb b/spec/public/controller/base_spec.rb
995 index 1709e612629ed2c2b6af4579a8b89684aca9aa3c..5bcdb59948cc22592639b1aee9bd233ff2c306fa 100644
996 --- a/spec/public/controller/base_spec.rb
997 +++ b/spec/public/controller/base_spec.rb
998 @@ -10,11 +10,11 @@ describe Merb::Controller, " callable actions" do
999 end
1000
1001 it "should dispatch to callable actions" do
1002 - dispatch_to(Merb::Test::Fixtures::TestFoo, :index).body.should == "index"
1003 + dispatch_to(Merb::Test::Fixtures::TestBase, :index).body.should == "index"
1004 end
1005
1006 it "should not dispatch to hidden actions" do
1007 - calling { dispatch_to(Merb::Test::Fixtures::TestFoo, :hidden) }.
1008 + calling { dispatch_to(Merb::Test::Fixtures::TestBase, :hidden) }.
1009 should raise_error(Merb::ControllerExceptions::ActionNotFound)
1010 end
1011
1012 diff --git a/spec/public/controller/controllers/base.rb b/spec/public/controller/controllers/base.rb
1013 index a1b3beb27899df781d943427d9b23945f02e14de..c4b69a440a9da3c3486208d2cb95ccb8bdb974b9 100644
1014 --- a/spec/public/controller/controllers/base.rb
1015 +++ b/spec/public/controller/controllers/base.rb
1016 @@ -3,7 +3,7 @@ module Merb::Test::Fixtures
1017 self._template_root = File.dirname(__FILE__) / "views"
1018 end
1019
1020 - class TestFoo < ControllerTesting
1021 + class TestBase < ControllerTesting
1022 def index
1023 "index"
1024 end
1025 diff --git a/spec/public/controller/controllers/responder.rb b/spec/public/controller/controllers/responder.rb
1026 new file mode 100644
1027 index 0000000000000000000000000000000000000000..867192e8f6e995a43fd5cd3daffa0ec11b3d31e5
1028 --- /dev/null
1029 +++ b/spec/public/controller/controllers/responder.rb
1030 @@ -0,0 +1,25 @@
1031 +module Merb::Test::Fixtures
1032 + class ControllerTesting < Merb::Controller
1033 + self._template_root = File.dirname(__FILE__) / "views"
1034 + end
1035 +
1036 + class TestResponder < ControllerTesting
1037 + def index
1038 + render
1039 + end
1040 + end
1041 +
1042 + class TestHtmlDefault < TestResponder; end
1043 +
1044 + class TestClassProvides < TestResponder;
1045 + provides :xml
1046 + end
1047 +
1048 + class TestLocalProvides < TestResponder;
1049 + def index
1050 + provides :xml
1051 + render
1052 + end
1053 + end
1054 +
1055 +end
1056 \ No newline at end of file
1057 diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.html.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.html.erb
1058 new file mode 100644
1059 index 0000000000000000000000000000000000000000..1bfb77d4a44c444bba6888ae7740f7df4b074c58
1060 --- /dev/null
1061 +++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.html.erb
1062 @@ -0,0 +1 @@
1063 +This should not be rendered
1064 \ No newline at end of file
1065 diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.xml.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.xml.erb
1066 new file mode 100644
1067 index 0000000000000000000000000000000000000000..7c91f633987348e87e5e34e1d9e87d9dd0e5100c
1068 --- /dev/null
1069 +++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_class_provides/index.xml.erb
1070 @@ -0,0 +1 @@
1071 +<XML:Class provides='true' />
1072 \ No newline at end of file
1073 diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_html_default/index.html.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_html_default/index.html.erb
1074 new file mode 100644
1075 index 0000000000000000000000000000000000000000..eb4b52bf5a7aaba8f1706de419f42789c05684a2
1076 --- /dev/null
1077 +++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_html_default/index.html.erb
1078 @@ -0,0 +1 @@
1079 +HTML: Default
1080 \ No newline at end of file
1081 diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.html.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.html.erb
1082 new file mode 100644
1083 index 0000000000000000000000000000000000000000..a3a841a89c62e6174038935a42da9cd24ff54413
1084 --- /dev/null
1085 +++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.html.erb
1086 @@ -0,0 +1 @@
1087 +This should not render
1088 \ No newline at end of file
1089 diff --git a/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.xml.erb b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.xml.erb
1090 new file mode 100644
1091 index 0000000000000000000000000000000000000000..c1384ec6af0357b585cc367035d1bc3a30347ade
1092 --- /dev/null
1093 +++ b/spec/public/controller/controllers/views/merb/test/fixtures/test_local_provides/index.xml.erb
1094 @@ -0,0 +1 @@
1095 +<XML:Local provides='true' />
1096 \ No newline at end of file
1097 diff --git a/spec/public/controller/responder_spec.rb b/spec/public/controller/responder_spec.rb
1098 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bcf18532442e5965cf6ca8501770d7b7a1eb2429 100644
1099 --- a/spec/public/controller/responder_spec.rb
1100 +++ b/spec/public/controller/responder_spec.rb
1101 @@ -0,0 +1,31 @@
1102 +require File.join(File.dirname(__FILE__), "spec_helper")
1103 +
1104 +describe Merb::Controller, " responds" do
1105 +
1106 + before do
1107 + Merb.push_path(:layout, File.dirname(__FILE__) / "controllers" / "views" / "layouts")
1108 + Merb::Router.prepare do |r|
1109 + r.default_routes
1110 + end
1111 + end
1112 +
1113 + it "should default the mime-type to HTML" do
1114 + dispatch_to(Merb::Test::Fixtures::TestHtmlDefault, :index).body.should == "HTML: Default"
1115 + end
1116 +
1117 + it "should use other mime-types if they are provided on the class level" do
1118 + controller = dispatch_to(Merb::Test::Fixtures::TestClassProvides, :index, {}, :http_accept => "application/xml")
1119 + controller.body.should == "<XML:Class provides='true' />"
1120 + end
1121 +
1122 + it "should fail if none of the acceptable mime-types are available" do
1123 + calling { dispatch_to(Merb::Test::Fixtures::TestClassProvides, :index, {}, :http_accept => "application/json") }.
1124 + should raise_error(Merb::ControllerExceptions::NotAcceptable)
1125 + end
1126 +
1127 + it "should use mime-types that are provided at the local level" do
1128 + controller = dispatch_to(Merb::Test::Fixtures::TestLocalProvides, :index, {}, :http_accept => "application/xml")
1129 + controller.body.should == "<XML:Local provides='true' />"
1130 + end
1131 +
1132 +end
1133 \ No newline at end of file
1134 diff --git a/spec/public/controller/spec_helper.rb b/spec/public/controller/spec_helper.rb
1135 index f68628a63740f4ce0235a15d71c5889e55ecaf78..e360194c1fbaf72c3298c61543c2d3a19b512b41 100644
1136 --- a/spec/public/controller/spec_helper.rb
1137 +++ b/spec/public/controller/spec_helper.rb
1138 @@ -1,4 +1,10 @@
1139 __DIR__ = File.dirname(__FILE__)
1140 +require 'ruby-debug'
1141 +
1142 require File.join(__DIR__, "..", "..", "spec_helper")
1143
1144 -require File.join(__DIR__, "controllers", "base")
1145 \ No newline at end of file
1146 +require File.join(__DIR__, "controllers", "base")
1147 +require File.join(__DIR__, "controllers", "responder")
1148 +
1149 +Merb::BootLoader::Templates.run
1150 +Merb::BootLoader::MimeTypes.run
1151 \ No newline at end of file
+0
-14
git/test/fixtures/diff_new_mode less more
0 diff --git a/conf/global_settings.py b/conf/global_settings.py
1 old mode 100644
2 new mode 100755
3 index 9ec1bac000000000000000000000000000000000..1c4f83b000000000000000000000000000000000
4 --- a/conf/global_settings.py
5 +++ b/conf/global_settings.py
6 @@ -58,6 +58,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
7 )
8
9 MIDDLEWARE_CLASSES = (
10 + "django.middleware.cache.CacheMiddleware",
11 "django.middleware.common.CommonMiddleware",
12 "django.contrib.sessions.middleware.SessionMiddleware",
13 "django.contrib.auth.middleware.AuthenticationMiddleware",
+0
-2
git/test/fixtures/diff_numstat less more
0 29 18 a.txt
1 0 5 b.txt
+0
-610
git/test/fixtures/diff_p less more
0 diff --git a/.gitignore b/.gitignore
1 index 4ebc8aea50e0a67e000ba29a30809d0a7b9b2666..2dd02534615434d88c51307beb0f0092f21fd103 100644
2 --- a/.gitignore
3 +++ b/.gitignore
4 @@ -1 +1,2 @@
5 coverage
6 +pkg
7 diff --git a/Manifest.txt b/Manifest.txt
8 index 641972d82c6d1b51122274ae8f6a0ecdfb56ee22..38bf80c54a526e76d74820a0f48606fe1ca7b1be 100644
9 --- a/Manifest.txt
10 +++ b/Manifest.txt
11 @@ -4,4 +4,31 @@ README.txt
12 Rakefile
13 bin/grit
14 lib/grit.rb
15 -test/test_grit.rb
16 \ No newline at end of file
17 +lib/grit/actor.rb
18 +lib/grit/blob.rb
19 +lib/grit/commit.rb
20 +lib/grit/errors.rb
21 +lib/grit/git.rb
22 +lib/grit/head.rb
23 +lib/grit/lazy.rb
24 +lib/grit/repo.rb
25 +lib/grit/tree.rb
26 +test/fixtures/blame
27 +test/fixtures/cat_file_blob
28 +test/fixtures/cat_file_blob_size
29 +test/fixtures/for_each_ref
30 +test/fixtures/ls_tree_a
31 +test/fixtures/ls_tree_b
32 +test/fixtures/rev_list
33 +test/fixtures/rev_list_single
34 +test/helper.rb
35 +test/profile.rb
36 +test/suite.rb
37 +test/test_actor.rb
38 +test/test_blob.rb
39 +test/test_commit.rb
40 +test/test_git.rb
41 +test/test_head.rb
42 +test/test_reality.rb
43 +test/test_repo.rb
44 +test/test_tree.rb
45 diff --git a/README.txt b/README.txt
46 index 8b1e02c0fb554eed2ce2ef737a68bb369d7527df..fca94f84afd7d749c62626011f972a509f6a5ac6 100644
47 --- a/README.txt
48 +++ b/README.txt
49 @@ -1,32 +1,185 @@
50 grit
51 - by FIX (your name)
52 - FIX (url)
53 + by Tom Preston-Werner
54 + grit.rubyforge.org
55
56 == DESCRIPTION:
57 +
58 +Grit is a Ruby library for extracting information from a git repository in and
59 +object oriented manner.
60 +
61 +== REQUIREMENTS:
62 +
63 +* git (http://git.or.cz) tested with 1.5.3.4
64 +
65 +== INSTALL:
66 +
67 +sudo gem install grit
68 +
69 +== USAGE:
70 +
71 +Grit gives you object model access to your git repository. Once you have
72 +created a repository object, you can traverse it to find parent commit(s),
73 +trees, blobs, etc.
74 +
75 += Initialize a Repo object
76 +
77 +The first step is to create a GitPython.Repo object to represent your repo. I
78 +include the Grit module so reduce typing.
79 +
80 + include Grit
81 + repo = Repo.new("/Users/tom/dev/grit")
82
83 -FIX (describe your package)
84 +In the above example, the directory /Users/tom/dev/grit is my working
85 +repo and contains the .git directory. You can also initialize Grit with a
86 +bare repo.
87
88 -== FEATURES/PROBLEMS:
89 + repo = Repo.new("/var/git/grit.git")
90
91 -* FIX (list of features or problems)
92 += Getting a list of commits
93
94 -== SYNOPSIS:
95 +From the Repo object, you can get a list of commits as an array of Commit
96 +objects.
97
98 - FIX (code sample of usage)
99 + repo.commits
100 + # => [#<GitPython.Commit "e80bbd2ce67651aa18e57fb0b43618ad4baf7750">,
101 + #<GitPython.Commit "91169e1f5fa4de2eaea3f176461f5dc784796769">,
102 + #<GitPython.Commit "038af8c329ef7c1bae4568b98bd5c58510465493">,
103 + #<GitPython.Commit "40d3057d09a7a4d61059bca9dca5ae698de58cbe">,
104 + #<GitPython.Commit "4ea50f4754937bf19461af58ce3b3d24c77311d9">]
105 +
106 +Called without arguments, Repo#commits returns a list of up to ten commits
107 +reachable by the master branch (starting at the latest commit). You can ask
108 +for commits beginning at a different branch, commit, tag, etc.
109
110 -== REQUIREMENTS:
111 + repo.commits('mybranch')
112 + repo.commits('40d3057d09a7a4d61059bca9dca5ae698de58cbe')
113 + repo.commits('v0.1')
114 +
115 +You can specify the maximum number of commits to return.
116
117 -* FIX (list of requirements)
118 + repo.commits('master', 100)
119 +
120 +If you need paging, you can specify a number of commits to skip.
121
122 -== INSTALL:
123 + repo.commits('master', 10, 20)
124 +
125 +The above will return commits 21-30 from the commit list.
126 +
127 += The Commit object
128 +
129 +Commit objects contain information about that commit.
130 +
131 + head = repo.commits.first
132 +
133 + head.id
134 + # => "e80bbd2ce67651aa18e57fb0b43618ad4baf7750"
135 +
136 + head.parents
137 + # => [#<GitPython.Commit "91169e1f5fa4de2eaea3f176461f5dc784796769">]
138 +
139 + head.tree
140 + # => #<GitPython.Tree "3536eb9abac69c3e4db583ad38f3d30f8db4771f">
141 +
142 + head.author
143 + # => #<GitPython.Actor "Tom Preston-Werner <tom@mojombo.com>">
144 +
145 + head.authored_date
146 + # => Wed Oct 24 22:02:31 -0700 2007
147 +
148 + head.committer
149 + # => #<GitPython.Actor "Tom Preston-Werner <tom@mojombo.com>">
150 +
151 + head.committed_date
152 + # => Wed Oct 24 22:02:31 -0700 2007
153 +
154 + head.message
155 + # => "add Actor inspect"
156 +
157 +You can traverse a commit's ancestry by chaining calls to #parents.
158 +
159 + repo.commits.first.parents[0].parents[0].parents[0]
160 +
161 +The above corresponds to master^^^ or master~3 in git parlance.
162 +
163 += The Tree object
164 +
165 +A tree records pointers to the contents of a directory. Let's say you want
166 +the root tree of the latest commit on the master branch.
167 +
168 + tree = repo.commits.first.tree
169 + # => #<GitPython.Tree "3536eb9abac69c3e4db583ad38f3d30f8db4771f">
170 +
171 + tree.id
172 + # => "3536eb9abac69c3e4db583ad38f3d30f8db4771f"
173 +
174 +Once you have a tree, you can get the contents.
175 +
176 + contents = tree.contents
177 + # => [#<GitPython.Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">,
178 + #<GitPython.Blob "81d2c27608b352814cbe979a6acd678d30219678">,
179 + #<GitPython.Tree "c3d07b0083f01a6e1ac969a0f32b8d06f20c62e5">,
180 + #<GitPython.Tree "4d00fe177a8407dbbc64a24dbfc564762c0922d8">]
181 +
182 +This tree contains two Blob objects and two Tree objects. The trees are
183 +subdirectories and the blobs are files. Trees below the root have additional
184 +attributes.
185 +
186 + contents.last.name
187 + # => "lib"
188 +
189 + contents.last.mode
190 + # => "040000"
191 +
192 +There is a convenience method that allows you to get a named sub-object
193 +from a tree.
194 +
195 + tree/"lib"
196 + # => #<GitPython.Tree "e74893a3d8a25cbb1367cf241cc741bfd503c4b2">
197 +
198 +You can also get a tree directly from the repo if you know its name.
199 +
200 + repo.tree
201 + # => #<GitPython.Tree "master">
202 +
203 + repo.tree("91169e1f5fa4de2eaea3f176461f5dc784796769")
204 + # => #<GitPython.Tree "91169e1f5fa4de2eaea3f176461f5dc784796769">
205 +
206 += The Blob object
207 +
208 +A blob represents a file. Trees often contain blobs.
209 +
210 + blob = tree.contents.first
211 + # => #<GitPython.Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">
212 +
213 +A blob has certain attributes.
214 +
215 + blob.id
216 + # => "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666"
217 +
218 + blob.name
219 + # => "README.txt"
220 +
221 + blob.mode
222 + # => "100644"
223 +
224 + blob.size
225 + # => 7726
226 +
227 +You can get the data of a blob as a string.
228 +
229 + blob.data
230 + # => "Grit is a library to ..."
231 +
232 +You can also get a blob directly from the repo if you know its name.
233
234 -* FIX (sudo gem install, anything else)
235 + repo.blob("4ebc8aea50e0a67e000ba29a30809d0a7b9b2666")
236 + # => #<GitPython.Blob "4ebc8aea50e0a67e000ba29a30809d0a7b9b2666">
237
238 == LICENSE:
239
240 (The MIT License)
241
242 -Copyright (c) 2007 FIX
243 +Copyright (c) 2007 Tom Preston-Werner
244
245 Permission is hereby granted, free of charge, to any person obtaining
246 a copy of this software and associated documentation files (the
247 diff --git a/Rakefile b/Rakefile
248 index 5bfb62163af455ca54422fd0b2e723ba1021ad12..72fde8c9ca87a1c992ce992bab13c3c4f13cddb9 100644
249 --- a/Rakefile
250 +++ b/Rakefile
251 @@ -4,11 +4,11 @@ require './lib/grit.rb'
252
253 Hoe.new('grit', GitPython.VERSION) do |p|
254 p.rubyforge_name = 'grit'
255 - # p.author = 'FIX'
256 - # p.email = 'FIX'
257 - # p.summary = 'FIX'
258 - # p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
259 - # p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
260 + p.author = 'Tom Preston-Werner'
261 + p.email = 'tom@rubyisawesome.com'
262 + p.summary = 'Object model interface to a git repo'
263 + p.description = p.paragraphs_of('README.txt', 2..2).join("\n\n")
264 + p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[2..-1].map { |u| u.strip }
265 p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
266 end
267
268 diff --git a/lib/grit.rb b/lib/grit.rb
269 index ae0792ae39d4891ebc1af996102a4f9df703394d..ae55fd7961ac49233f6ca515622a61e90d516044 100644
270 --- a/lib/grit.rb
271 +++ b/lib/grit.rb
272 @@ -1,4 +1,4 @@
273 -$:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
274 +$:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
275
276 # core
277
278 @@ -12,6 +12,8 @@ require 'grit/head'
279 require 'grit/commit'
280 require 'grit/tree'
281 require 'grit/blob'
282 +require 'grit/actor'
283 +require 'grit/diff'
284 require 'grit/repo'
285
286 module Grit
287 @@ -21,5 +23,5 @@ module Grit
288
289 self.debug = false
290
291 - VERSION = '1.0.0'
292 + VERSION = '0.1.0'
293 end
294 \ No newline at end of file
295 diff --git a/lib/grit/actor.rb b/lib/grit/actor.rb
296 new file mode 100644
297 index 0000000000000000000000000000000000000000..f733bce6b57c0e5e353206e692b0e3105c2527f4
298 --- /dev/null
299 +++ b/lib/grit/actor.rb
300 @@ -0,0 +1,35 @@
301 +module Grit
302 +
303 + class Actor
304 + attr_reader :name
305 + attr_reader :email
306 +
307 + def initialize(name, email)
308 + @name = name
309 + @email = email
310 + end
311 +
312 + # Create an Actor from a string.
313 + # +str+ is the string, which is expected to be in regular git format
314 + #
315 + # Format
316 + # John Doe <jdoe@example.com>
317 + #
318 + # Returns Actor
319 + def self.from_string(str)
320 + case str
321 + when /<.+>/
322 + m, name, email = *str.match(/(.*) <(.+?)>/)
323 + return self.new(name, email)
324 + else
325 + return self.new(str, nil)
326 + end
327 + end
328 +
329 + # Pretty object inspection
330 + def inspect
331 + %Q{#<GitPython.Actor "#{@name} <#{@email}>">}
332 + end
333 + end # Actor
334 +
335 +end # Grit
336 \ No newline at end of file
337 diff --git a/lib/grit/blob.rb b/lib/grit/blob.rb
338 index c863646d4278bfee2a7bcb64caace6b31f89ef03..87d43fab37844afdc2f8814dba3abdaa791f1370 100644
339 --- a/lib/grit/blob.rb
340 +++ b/lib/grit/blob.rb
341 @@ -81,9 +81,9 @@ module Grit
342 c = commits[info[:id]]
343 unless c
344 c = Commit.create(repo, :id => info[:id],
345 - :author => info[:author],
346 + :author => Actor.from_string(info[:author] + ' ' + info[:author_email]),
347 :authored_date => info[:author_date],
348 - :committer => info[:committer],
349 + :committer => Actor.from_string(info[:committer] + ' ' + info[:committer_email]),
350 :committed_date => info[:committer_date],
351 :message => info[:summary])
352 commits[info[:id]] = c
353 @@ -102,11 +102,6 @@ module Grit
354 def inspect
355 %Q{#<GitPython.Blob "#{@id}">}
356 end
357 -
358 - # private
359 -
360 - def self.read_
361 - end
362 end # Blob
363
364 end # Grit
365 \ No newline at end of file
366 diff --git a/lib/grit/commit.rb b/lib/grit/commit.rb
367 index c2a9e2f81657b19925fe9bab4bc5d7ac130e5880..cd9c3e3184c97e83a8982fab9499cad3aec339f6 100644
368 --- a/lib/grit/commit.rb
369 +++ b/lib/grit/commit.rb
370 @@ -136,6 +136,11 @@ module Grit
371 commits
372 end
373
374 + def self.diff(repo, id)
375 + text = repo.git.diff({:full_index => true}, id)
376 + Diff.list_from_string(repo, text)
377 + end
378 +
379 # Convert this Commit to a String which is just the SHA1 id
380 def to_s
381 @id
382 @@ -153,7 +158,7 @@ module Grit
383 # Returns [String (actor name and email), Time (acted at time)]
384 def self.actor(line)
385 m, actor, epoch = *line.match(/^.+? (.*) (\d+) .*$/)
386 - [actor, Time.at(epoch.to_i)]
387 + [Actor.from_string(actor), Time.at(epoch.to_i)]
388 end
389 end # Commit
390
391 diff --git a/lib/grit/git.rb b/lib/grit/git.rb
392 index 1d5251d40fb65ac89184ec662a3e1b04d0c24861..98eeddda5ed2b0e215e21128112393bdc9bc9039 100644
393 --- a/lib/grit/git.rb
394 +++ b/lib/grit/git.rb
395 @@ -13,17 +13,6 @@ module Grit
396 self.git_dir = git_dir
397 end
398
399 - # Converstion hash from Ruby style options to git command line
400 - # style options
401 - TRANSFORM = {:max_count => "--max-count=",
402 - :skip => "--skip=",
403 - :pretty => "--pretty=",
404 - :sort => "--sort=",
405 - :format => "--format=",
406 - :since => "--since=",
407 - :p => "-p",
408 - :s => "-s"}
409 -
410 # Run the given git command with the specified arguments and return
411 # the result as a String
412 # +cmd+ is the command
413 @@ -52,12 +41,19 @@ module Grit
414 def transform_options(options)
415 args = []
416 options.keys.each do |opt|
417 - if TRANSFORM[opt]
418 + if opt.to_s.size == 1
419 + if options[opt] == true
420 + args << "-#{opt}"
421 + else
422 + val = options.delete(opt)
423 + args << "-#{opt.to_s} #{val}"
424 + end
425 + else
426 if options[opt] == true
427 - args << TRANSFORM[opt]
428 + args << "--#{opt.to_s.gsub(/_/, '-')}"
429 else
430 val = options.delete(opt)
431 - args << TRANSFORM[opt] + val.to_s
432 + args << "--#{opt.to_s.gsub(/_/, '-')}=#{val}"
433 end
434 end
435 end
436 diff --git a/lib/grit/repo.rb b/lib/grit/repo.rb
437 index 624991d07e240ae66ff2a0dc55e2f2b5e262c75b..63bf03b839374c96a3d42a07d56681a797f52a71 100644
438 --- a/lib/grit/repo.rb
439 +++ b/lib/grit/repo.rb
440 @@ -93,6 +93,17 @@ module Grit
441 def blob(id)
442 Blob.create(self, :id => id)
443 end
444 +
445 + # The commit log for a treeish
446 + #
447 + # Returns GitPython.Commit[]
448 + def log(commit = 'master', path = nil, options = {})
449 + default_options = {:pretty => "raw"}
450 + actual_options = default_options.merge(options)
451 + arg = path ? "#{commit} -- #{path}" : commit
452 + commits = self.git.log(actual_options, arg)
453 + Commit.list_from_string(self, commits)
454 + end
455
456 # The diff from commit +a+ to commit +b+, optionally restricted to the given file(s)
457 # +a+ is the base commit
458 @@ -121,4 +132,4 @@ module Grit
459 end
460 end # Repo
461
462 -end # Grit
463 \ No newline at end of file
464 +end # Grit
465 diff --git a/test/test_actor.rb b/test/test_actor.rb
466 new file mode 100644
467 index 0000000000000000000000000000000000000000..08391f12336831d048122c8d13bc8404f27e6b91
468 --- /dev/null
469 +++ b/test/test_actor.rb
470 @@ -0,0 +1,28 @@
471 +require File.dirname(__FILE__) + '/helper'
472 +
473 +class TestActor < Test::Unit::TestCase
474 + def setup
475 +
476 + end
477 +
478 + # from_string
479 +
480 + def test_from_string_should_separate_name_and_email
481 + a = Actor.from_string("Tom Werner <tom@example.com>")
482 + assert_equal "Tom Werner", a.name
483 + assert_equal "tom@example.com", a.email
484 + end
485 +
486 + def test_from_string_should_handle_just_name
487 + a = Actor.from_string("Tom Werner")
488 + assert_equal "Tom Werner", a.name
489 + assert_equal nil, a.email
490 + end
491 +
492 + # inspect
493 +
494 + def test_inspect
495 + a = Actor.from_string("Tom Werner <tom@example.com>")
496 + assert_equal %Q{#<GitPython.Actor "Tom Werner <tom@example.com>">}, a.inspect
497 + end
498 +end
499 \ No newline at end of file
500 diff --git a/test/test_blob.rb b/test/test_blob.rb
501 index 6fa087d785661843034d03c7e0b917a8a80d5d8c..9ef84cc14266141b070771706b8aeebc3dfbef82 100644
502 --- a/test/test_blob.rb
503 +++ b/test/test_blob.rb
504 @@ -40,9 +40,11 @@ class TestBlob < Test::Unit::TestCase
505 c = b.first.first
506 c.expects(:__bake__).times(0)
507 assert_equal '634396b2f541a9f2d58b00be1a07f0c358b999b3', c.id
508 - assert_equal 'Tom Preston-Werner', c.author
509 + assert_equal 'Tom Preston-Werner', c.author.name
510 + assert_equal 'tom@mojombo.com', c.author.email
511 assert_equal Time.at(1191997100), c.authored_date
512 - assert_equal 'Tom Preston-Werner', c.committer
513 + assert_equal 'Tom Preston-Werner', c.committer.name
514 + assert_equal 'tom@mojombo.com', c.committer.email
515 assert_equal Time.at(1191997100), c.committed_date
516 assert_equal 'initial grit setup', c.message
517 # c.expects(:__bake__).times(1)
518 diff --git a/test/test_commit.rb b/test/test_commit.rb
519 index 3bd6af75deda05725900eb7fd06e8107df14c655..0936c90e5b29ede2b5214d6dc26d256a8c6646f4 100644
520 --- a/test/test_commit.rb
521 +++ b/test/test_commit.rb
522 @@ -10,9 +10,28 @@ class TestCommit < Test::Unit::TestCase
523 def test_bake
524 Git.any_instance.expects(:rev_list).returns(fixture('rev_list_single'))
525 @c = Commit.create(@r, :id => '4c8124ffcf4039d292442eeccabdeca5af5c5017')
526 - @c.author # cause bake-age
527 + @c.author # bake
528
529 - assert_equal "Tom Preston-Werner <tom@mojombo.com>", @c.author
530 + assert_equal "Tom Preston-Werner", @c.author.name
531 + assert_equal "tom@mojombo.com", @c.author.email
532 + end
533 +
534 + # diff
535 +
536 + def test_diff
537 + Git.any_instance.expects(:diff).returns(fixture('diff_p'))
538 + diffs = Commit.diff(@r, 'master')
539 +
540 + assert_equal 15, diffs.size
541 +
542 + assert_equal '.gitignore', diffs.first.a_path
543 + assert_equal '.gitignore', diffs.first.b_path
544 + assert_equal '4ebc8ae', diffs.first.a_commit
545 + assert_equal '2dd0253', diffs.first.b_commit
546 + assert_equal '100644', diffs.first.mode
547 + assert_equal false, diffs.first.new_file
548 + assert_equal false, diffs.first.deleted_file
549 + assert_equal "--- a/.gitignore\n+++ b/.gitignore\n@@ -1 +1,2 @@\n coverage\n+pkg", diffs.first.diff
550 end
551
552 # to_s
553 diff --git a/test/test_git.rb b/test/test_git.rb
554 index e615a035d096b6cbc984e2f4213c06d0ac785321..72a18ec424f078f6daee75dbc62265c02ba7a892 100644
555 --- a/test/test_git.rb
556 +++ b/test/test_git.rb
557 @@ -10,6 +10,12 @@ class TestGit < Test::Unit::TestCase
558 end
559
560 def test_transform_options
561 + assert_equal ["-s"], @git.transform_options({:s => true})
562 + assert_equal ["-s 5"], @git.transform_options({:s => 5})
563 +
564 + assert_equal ["--max-count"], @git.transform_options({:max_count => true})
565 assert_equal ["--max-count=5"], @git.transform_options({:max_count => 5})
566 +
567 + assert_equal ["-t", "-s"], @git.transform_options({:s => true, :t => true})
568 end
569 end
570 \ No newline at end of file
571 diff --git a/test/test_repo.rb b/test/test_repo.rb
572 index d53476a51e3286be270c7b515ec1d65e5c1716e0..114a4464fa248550be10cc4abe0735d6025b5fca 100644
573 --- a/test/test_repo.rb
574 +++ b/test/test_repo.rb
575 @@ -59,9 +59,11 @@ class TestRepo < Test::Unit::TestCase
576 assert_equal '4c8124ffcf4039d292442eeccabdeca5af5c5017', c.id
577 assert_equal ["634396b2f541a9f2d58b00be1a07f0c358b999b3"], c.parents.map { |p| p.id }
578 assert_equal "672eca9b7f9e09c22dcb128c283e8c3c8d7697a4", c.tree.id
579 - assert_equal "Tom Preston-Werner <tom@mojombo.com>", c.author
580 + assert_equal "Tom Preston-Werner", c.author.name
581 + assert_equal "tom@mojombo.com", c.author.email
582 assert_equal Time.at(1191999972), c.authored_date
583 - assert_equal "Tom Preston-Werner <tom@mojombo.com>", c.committer
584 + assert_equal "Tom Preston-Werner", c.committer.name
585 + assert_equal "tom@mojombo.com", c.committer.email
586 assert_equal Time.at(1191999972), c.committed_date
587 assert_equal "implement Grit#heads", c.message
588
589 @@ -125,4 +127,18 @@ class TestRepo < Test::Unit::TestCase
590 def test_inspect
591 assert_equal %Q{#<GitPython.Repo "#{File.expand_path(GRIT_REPO)}/.git">}, @r.inspect
592 end
593 -end
594 \ No newline at end of file
595 +
596 + # log
597 +
598 + def test_log
599 + Git.any_instance.expects(:log).times(2).with({:pretty => 'raw'}, 'master').returns(fixture('rev_list'))
600 +
601 + assert_equal '4c8124ffcf4039d292442eeccabdeca5af5c5017', @r.log.first.id
602 + assert_equal 'ab25fd8483882c3bda8a458ad2965d2248654335', @r.log.last.id
603 + end
604 +
605 + def test_log_with_path_and_options
606 + Git.any_instance.expects(:log).with({:pretty => 'raw', :max_count => 1}, 'master -- file.rb').returns(fixture('rev_list'))
607 + @r.log('master', 'file.rb', :max_count => 1)
608 + end
609 +end
+0
-3
git/test/fixtures/diff_patch_binary less more
0 diff --git a/rps b/rps
1 index f4567df37451b230b1381b1bc9c2bcad76e08a3c..736bd596a36924d30b480942e9475ce0d734fa0d 100755
2 Binary files a/rps and b/rps differ
+0
-89
git/test/fixtures/diff_patch_unsafe_paths less more
0 diff --git a/path/ starting with a space b/path/ starting with a space
1 new file mode 100644
2 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
3 --- /dev/null
4 +++ b/path/ starting with a space
5 @@ -0,0 +1 @@
6 +dummy content
7 diff --git "a/path/\"with-quotes\"" "b/path/\"with-quotes\""
8 new file mode 100644
9 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
10 --- /dev/null
11 +++ "b/path/\"with-quotes\""
12 @@ -0,0 +1 @@
13 +dummy content
14 diff --git a/path/'with-single-quotes' b/path/'with-single-quotes'
15 new file mode 100644
16 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
17 --- /dev/null
18 +++ b/path/'with-single-quotes'
19 @@ -0,0 +1 @@
20 +dummy content
21 diff --git a/path/ending in a space b/path/ending in a space
22 new file mode 100644
23 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
24 --- /dev/null
25 +++ b/path/ending in a space
26 @@ -0,0 +1 @@
27 +dummy content
28 diff --git "a/path/with\ttab" "b/path/with\ttab"
29 new file mode 100644
30 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
31 --- /dev/null
32 +++ "b/path/with\ttab"
33 @@ -0,0 +1 @@
34 +dummy content
35 diff --git "a/path/with\nnewline" "b/path/with\nnewline"
36 new file mode 100644
37 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
38 --- /dev/null
39 +++ "b/path/with\nnewline"
40 @@ -0,0 +1 @@
41 +dummy content
42 diff --git a/path/with spaces b/path/with spaces
43 new file mode 100644
44 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
45 --- /dev/null
46 +++ b/path/with spaces
47 @@ -0,0 +1 @@
48 +dummy content
49 diff --git a/path/with-question-mark? b/path/with-question-mark?
50 new file mode 100644
51 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
52 --- /dev/null
53 +++ b/path/with-question-mark?
54 @@ -0,0 +1 @@
55 +dummy content
56 diff --git "a/path/¯\\_(ツ)_|¯" "b/path/¯\\_(ツ)_|¯"
57 new file mode 100644
58 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
59 --- /dev/null
60 +++ "b/path/¯\\_(ツ)_|¯"
61 @@ -0,0 +1 @@
62 +dummy content
63 diff --git "a/path/\360\237\222\251.txt" "b/path/\360\237\222\251.txt"
64 new file mode 100644
65 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
66 --- /dev/null
67 +++ "b/path/\360\237\222\251.txt"
68 @@ -0,0 +1 @@
69 +dummy content
70 diff --git "a/path/\200-invalid-unicode-path.txt" "b/path/\200-invalid-unicode-path.txt"
71 new file mode 100644
72 index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
73 --- /dev/null
74 +++ "b/path/\200-invalid-unicode-path.txt"
75 @@ -0,0 +1 @@
76 +dummy content
77 diff --git a/a/with spaces b/b/with some spaces
78 similarity index 100%
79 rename from a/with spaces
80 rename to b/with some spaces
81 diff --git a/a/ending in a space b/b/ending with space
82 similarity index 100%
83 rename from a/ending in a space
84 rename to b/ending with space
85 diff --git "a/a/\"with-quotes\"" "b/b/\"with even more quotes\""
86 similarity index 100%
87 rename from "a/\"with-quotes\""
88 rename to "b/\"with even more quotes\""
+0
-1
git/test/fixtures/diff_raw_binary less more
0 :100755 100755 f4567df37451b230b1381b1bc9c2bcad76e08a3c 736bd596a36924d30b480942e9475ce0d734fa0d M rps
+0
-12
git/test/fixtures/diff_rename less more
0 commit 2524c44334a8ba6b2ab8f3f0a478f04c5b073cc8
1 tree e126e7b4203dadf083f5eb8e2f34c255b51d8bee
2 parent d789e23b9ea8d90221d13c46f7c228d729385f92
3 author Michael Trier <mtrier@gmail.com> 1229389391 -0500
4 committer Michael Trier <mtrier@gmail.com> 1229389391 -0500
5
6 Renamed AUTHORS to CONTRIBUTORS because it's cooler.
7
8 diff --git a/AUTHORS b/CONTRIBUTORS
9 similarity index 100%
10 rename from Jérôme
11 rename to müller
+0
-1
git/test/fixtures/diff_rename_raw less more
0 :100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 R100 this that
+0
-3
git/test/fixtures/diff_tree_numstat_root less more
0 634396b2f541a9f2d58b00be1a07f0c358b999b3
1 18 29 a.txt
2 5 0 b.txt
git/test/fixtures/for_each_ref_with_path_component less more
Binary diff not shown
+0
-46
git/test/fixtures/git_config less more
0 [core]
1 repositoryformatversion = 0
2 filemode = true
3 bare = false
4 logallrefupdates = true
5 [remote "origin"]
6 fetch = +refs/heads/*:refs/remotes/origin/*
7 url = git://gitorious.org/~byron/git-python/byrons-clone.git
8 pushurl = git@gitorious.org:~byron/git-python/byrons-clone.git
9 # a tab indented section header
10 [branch "master"]
11 remote = origin
12 merge = refs/heads/master
13 # an space indented section header
14 [remote "mainline"]
15 # space indented comment
16 url = git://gitorious.org/git-python/mainline.git
17 fetch = +refs/heads/*:refs/remotes/mainline/*
18
19 [remote "MartinMarcher"]
20 # tab indented comment
21 url = git://gitorious.org/~martin.marcher/git-python/serverhorror.git
22 fetch = +refs/heads/*:refs/remotes/MartinMarcher/*
23 # can handle comments - the section name is supposed to be stripped
24 # causes stock git-config puke
25 [ gui ]
26 geometry = 1316x820+219+243 207 192
27 [branch "mainline_performance"]
28 remote = mainline
29 merge = refs/heads/master
30 # section with value defined before include to be overriden
31 [sec]
32 var0 = value0_main
33 [include]
34 path = doesntexist.cfg
35 # field should be 'path' so abspath should be ignored
36 abspath = /usr/bin/foodoesntexist.bar
37 path = /usr/bin/foodoesntexist.bar
38 # should be relative to the path of this config file
39 path = ./git_config-inc.cfg
40 # and defined after include. According to the documentation
41 # and behavior of git config, this should be the value since
42 # inclusions should be processed immediately
43 [sec]
44 var1 = value1_main
45
+0
-5
git/test/fixtures/git_config-inc.cfg less more
0 [sec]
1 var0 = value0_included
2 var1 = value1_included
3 [diff]
4 tool = diff_included
+0
-25
git/test/fixtures/git_config_global less more
0 # just a comment
1 [alias]
2 st = status
3 ci = commit
4 co = checkout
5 br = branch
6 [color]
7 branch = auto
8 diff = auto
9 interactive = auto
10 status = auto
11 [user]
12 name = Sebastian Thiel
13 email = byronimo@gmail.com
14 [core]
15 editor = vim
16 autocrlf = false
17 packedGitLimit = 1g
18 packedGitWindowSize = 512m
19 [pack]
20 windowMemory = 512m
21 [merge]
22 tool = meld
23 [diff]
24 tool = meld
+0
-7
git/test/fixtures/git_config_multiple less more
0 [section0]
1 option0 = value0
2
3 [section1]
4 option1 = value1a
5 option1 = value1b
6 other_option1 = other_value1
+0
-183
git/test/fixtures/git_config_with_comments less more
0 [user]
1 name = Cody Veal
2 email = cveal05@gmail.com
3
4 [github]
5 user = cjhveal
6
7 [advice]
8 statusHints = false
9
10 [alias]
11 # add
12 a = add
13 aa = add --all
14 ap = add --patch
15
16 aliases = !git config --list | grep 'alias\\.' | sed 's/alias\\.\\([^=]*\\)=\\(.*\\)/\\1\\\t => \\2/' | sort
17
18 # branch
19 br = branch
20 branches = branch -av
21 cp = cherry-pick
22 diverges = !bash -c 'diff -u <(git rev-list --first-parent "${1}") <(git rev-list --first-parent "${2:-HEAD}"g | sed -ne \"s/^ //p\" | head -1' -
23 track = checkout -t
24 nb = checkout -b
25
26 # commit
27 amend = commit --amend -C HEAD
28 c = commit
29 ca = commit --amend
30 cm = commit --message
31 msg = commit --allow-empty -m
32
33 co = checkout
34
35 # diff
36 d = diff --color-words # diff by word
37 ds = diff --staged --color-words
38 dd = diff --color-words=. # diff by char
39 dds = diff --staged --color-words=.
40 dl = diff # diff by line
41 dls = diff --staged
42
43 h = help
44
45 # log
46 authors = "!git log --pretty=format:%aN | sort | uniq -c | sort -rn"
47 lc = log ORIG_HEAD.. --stat --no-merges
48 lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative
49 lol = log --graph --decorate --pretty=oneline --abbrev-commit
50 lola = log --graph --decorate --pretty=oneline --abbrev-commit --all
51
52 # merge
53 m = merge
54 mm = merge --no-ff
55 ours = "!f() { git checkout --ours $@ && git add $@; }; f"
56 theirs = "!f() { git checkout --theirs $@ && git add $@; }; f"
57
58 # push/pull
59 l = pull
60 p = push
61 sync = !git pull && git push
62
63 # remotes
64 prune-remotes = "!for remote in `git remote`; do git remote prune $remote; done"
65 r = remote
66
67 # rebase
68 rb = rebase
69 rba = rebase --abort
70 rbc = rebase --continue
71 rbs = rebase --skip
72
73 # reset
74 rh = reset --hard
75 rhh = reset HEAD --hard
76 uncommit = reset --soft HEAD^
77 unstage = reset HEAD --
78 unpush = push -f origin HEAD^:master
79
80 # stash
81 ss = stash
82 sl = stash list
83 sp = stash pop
84 sd = stash drop
85 snapshot = !git stash save "snapshot: $(date)" && git stash apply "stash@{0}"
86
87 # status
88 s = status --short --branch
89 st = status
90
91 # submodule
92 sm = submodule
93 sma = submodule add
94 smu = submodule update --init
95 pup = !git pull && git submodule init && git submodule update
96
97 # file level ignoring
98 assume = update-index --assume-unchanged
99 unassume = update-index --no-assume-unchanged
100 assumed = "!git ls-files -v | grep ^h | cut -c 3-"
101
102
103 [apply]
104 whitespace = fix
105
106 [color]
107 ui = auto
108
109 [color "branch"]
110 current = yellow reverse
111 local = yellow
112 remote = green
113
114 [color "diff"]
115 meta = yellow
116 frag = magenta
117 old = red bold
118 new = green bold
119 whitespace = red reverse
120
121 [color "status"]
122 added = green
123 changed = yellow
124 untracked = cyan
125
126 [core]
127 editor = /usr/bin/vim
128 excludesfile = ~/.gitignore_global
129 attributesfile = ~/.gitattributes
130
131 [diff]
132 renames = copies
133 mnemonicprefix = true
134
135 [diff "zip"]
136 textconv = unzip -c -a
137
138 [merge]
139 log = true
140
141 [merge "railsschema"]
142 name = newer Rails schema version
143 driver = "ruby -e '\n\
144 system %(git), %(merge-file), %(--marker-size=%L), %(%A), %(%O), %(%B)\n\
145 b = File.read(%(%A))\n\
146 b.sub!(/^<+ .*\\nActiveRecord::Schema\\.define.:version => (\\d+). do\\n=+\\nActiveRecord::Schema\\.define.:version => (\\d+). do\\n>+ .*/) do\n\
147 %(ActiveRecord::Schema.define(:version => #{[$1, $2].max}) do)\n\
148 end\n\
149 File.open(%(%A), %(w)) {|f| f.write(b)}\n\
150 exit 1 if b.include?(%(<)*%L)'"
151
152 [merge "gemfilelock"]
153 name = relocks the gemfile.lock
154 driver = bundle lock
155
156 [pager]
157 color = true
158
159 [push]
160 default = upstream
161
162 [rerere]
163 enabled = true
164
165 [url "git@github.com:"]
166 insteadOf = "gh:"
167 pushInsteadOf = "github:"
168 pushInsteadOf = "git://github.com/"
169
170 [url "git://github.com/"]
171 insteadOf = "github:"
172
173 [url "git@gist.github.com:"]
174 insteadOf = "gst:"
175 pushInsteadOf = "gist:"
176 pushInsteadOf = "git://gist.github.com/"
177
178 [url "git://gist.github.com/"]
179 insteadOf = "gist:"
180
181 [url "git@heroku.com:"]
182 insteadOf = "heroku:"
+0
-4
git/test/fixtures/git_config_with_empty_value less more
0 [color]
1 ui
2 [core]
3 filemode = true
+0
-1
git/test/fixtures/git_file less more
0 gitdir: ./.real
git/test/fixtures/index less more
Binary diff not shown
git/test/fixtures/index_merge less more
Binary diff not shown
+0
-5002
git/test/fixtures/issue-301_stderr less more
0 From github.com:jantman/gitpython_issue_301
1 = [up to date] master -> origin/master
2 = [up to date] testcommit1 -> origin/testcommit1
3 = [up to date] testcommit10 -> origin/testcommit10
4 = [up to date] testcommit100 -> origin/testcommit100
5 = [up to date] testcommit1000 -> origin/testcommit1000
6 = [up to date] testcommit1001 -> origin/testcommit1001
7 = [up to date] testcommit1002 -> origin/testcommit1002
8 = [up to date] testcommit1003 -> origin/testcommit1003
9 = [up to date] testcommit1004 -> origin/testcommit1004
10 = [up to date] testcommit1005 -> origin/testcommit1005
11 = [up to date] testcommit1006 -> origin/testcommit1006
12 = [up to date] testcommit1007 -> origin/testcommit1007
13 = [up to date] testcommit1008 -> origin/testcommit1008
14 = [up to date] testcommit1009 -> origin/testcommit1009
15 = [up to date] testcommit101 -> origin/testcommit101
16 = [up to date] testcommit1010 -> origin/testcommit1010
17 = [up to date] testcommit1011 -> origin/testcommit1011
18 = [up to date] testcommit1012 -> origin/testcommit1012
19 = [up to date] testcommit1013 -> origin/testcommit1013
20 = [up to date] testcommit1014 -> origin/testcommit1014
21 = [up to date] testcommit1015 -> origin/testcommit1015
22 = [up to date] testcommit1016 -> origin/testcommit1016
23 = [up to date] testcommit1017 -> origin/testcommit1017
24 = [up to date] testcommit1018 -> origin/testcommit1018
25 = [up to date] testcommit1019 -> origin/testcommit1019
26 = [up to date] testcommit102 -> origin/testcommit102
27 = [up to date] testcommit1020 -> origin/testcommit1020
28 = [up to date] testcommit1021 -> origin/testcommit1021
29 = [up to date] testcommit1022 -> origin/testcommit1022
30 = [up to date] testcommit1023 -> origin/testcommit1023
31 = [up to date] testcommit1024 -> origin/testcommit1024
32 = [up to date] testcommit1025 -> origin/testcommit1025
33 = [up to date] testcommit1026 -> origin/testcommit1026
34 = [up to date] testcommit1027 -> origin/testcommit1027
35 = [up to date] testcommit1028 -> origin/testcommit1028
36 = [up to date] testcommit1029 -> origin/testcommit1029
37 = [up to date] testcommit103 -> origin/testcommit103
38 = [up to date] testcommit1030 -> origin/testcommit1030
39 = [up to date] testcommit1031 -> origin/testcommit1031
40 = [up to date] testcommit1032 -> origin/testcommit1032
41 = [up to date] testcommit1033 -> origin/testcommit1033
42 = [up to date] testcommit1034 -> origin/testcommit1034
43 = [up to date] testcommit1035 -> origin/testcommit1035
44 = [up to date] testcommit1036 -> origin/testcommit1036
45 = [up to date] testcommit1037 -> origin/testcommit1037
46 = [up to date] testcommit1038 -> origin/testcommit1038
47 = [up to date] testcommit1039 -> origin/testcommit1039
48 = [up to date] testcommit104 -> origin/testcommit104
49 = [up to date] testcommit1040 -> origin/testcommit1040
50 = [up to date] testcommit1041 -> origin/testcommit1041
51 = [up to date] testcommit1042 -> origin/testcommit1042
52 = [up to date] testcommit1043 -> origin/testcommit1043
53 = [up to date] testcommit1044 -> origin/testcommit1044
54 = [up to date] testcommit1045 -> origin/testcommit1045
55 = [up to date] testcommit1046 -> origin/testcommit1046
56 = [up to date] testcommit1047 -> origin/testcommit1047
57 = [up to date] testcommit1048 -> origin/testcommit1048
58 = [up to date] testcommit1049 -> origin/testcommit1049
59 = [up to date] testcommit105 -> origin/testcommit105
60 = [up to date] testcommit1050 -> origin/testcommit1050
61 = [up to date] testcommit1051 -> origin/testcommit1051
62 = [up to date] testcommit1052 -> origin/testcommit1052
63 = [up to date] testcommit1053 -> origin/testcommit1053
64 = [up to date] testcommit1054 -> origin/testcommit1054
65 = [up to date] testcommit1055 -> origin/testcommit1055
66 = [up to date] testcommit1056 -> origin/testcommit1056
67 = [up to date] testcommit1057 -> origin/testcommit1057
68 = [up to date] testcommit1058 -> origin/testcommit1058
69 = [up to date] testcommit1059 -> origin/testcommit1059
70 = [up to date] testcommit106 -> origin/testcommit106
71 = [up to date] testcommit1060 -> origin/testcommit1060
72 = [up to date] testcommit1061 -> origin/testcommit1061
73 = [up to date] testcommit1062 -> origin/testcommit1062
74 = [up to date] testcommit1063 -> origin/testcommit1063
75 = [up to date] testcommit1064 -> origin/testcommit1064
76 = [up to date] testcommit1065 -> origin/testcommit1065
77 = [up to date] testcommit1066 -> origin/testcommit1066
78 = [up to date] testcommit1067 -> origin/testcommit1067
79 = [up to date] testcommit1068 -> origin/testcommit1068
80 = [up to date] testcommit1069 -> origin/testcommit1069
81 = [up to date] testcommit107 -> origin/testcommit107
82 = [up to date] testcommit1070 -> origin/testcommit1070
83 = [up to date] testcommit1071 -> origin/testcommit1071
84 = [up to date] testcommit1072 -> origin/testcommit1072
85 = [up to date] testcommit1073 -> origin/testcommit1073
86 = [up to date] testcommit1074 -> origin/testcommit1074
87 = [up to date] testcommit1075 -> origin/testcommit1075
88 = [up to date] testcommit1076 -> origin/testcommit1076
89 = [up to date] testcommit1077 -> origin/testcommit1077
90 = [up to date] testcommit1078 -> origin/testcommit1078
91 = [up to date] testcommit1079 -> origin/testcommit1079
92 = [up to date] testcommit108 -> origin/testcommit108
93 = [up to date] testcommit1080 -> origin/testcommit1080
94 = [up to date] testcommit1081 -> origin/testcommit1081
95 = [up to date] testcommit1082 -> origin/testcommit1082
96 = [up to date] testcommit1083 -> origin/testcommit1083
97 = [up to date] testcommit1084 -> origin/testcommit1084
98 = [up to date] testcommit1085 -> origin/testcommit1085
99 = [up to date] testcommit1086 -> origin/testcommit1086
100 = [up to date] testcommit1087 -> origin/testcommit1087
101 = [up to date] testcommit1088 -> origin/testcommit1088
102 = [up to date] testcommit1089 -> origin/testcommit1089
103 = [up to date] testcommit109 -> origin/testcommit109
104 = [up to date] testcommit1090 -> origin/testcommit1090
105 = [up to date] testcommit1091 -> origin/testcommit1091
106 = [up to date] testcommit1092 -> origin/testcommit1092
107 = [up to date] testcommit1093 -> origin/testcommit1093
108 = [up to date] testcommit1094 -> origin/testcommit1094
109 = [up to date] testcommit1095 -> origin/testcommit1095
110 = [up to date] testcommit1096 -> origin/testcommit1096
111 = [up to date] testcommit1097 -> origin/testcommit1097
112 = [up to date] testcommit1098 -> origin/testcommit1098
113 = [up to date] testcommit1099 -> origin/testcommit1099
114 = [up to date] testcommit11 -> origin/testcommit11
115 = [up to date] testcommit110 -> origin/testcommit110
116 = [up to date] testcommit1100 -> origin/testcommit1100
117 = [up to date] testcommit1101 -> origin/testcommit1101
118 = [up to date] testcommit1102 -> origin/testcommit1102
119 = [up to date] testcommit1103 -> origin/testcommit1103
120 = [up to date] testcommit1104 -> origin/testcommit1104
121 = [up to date] testcommit1105 -> origin/testcommit1105
122 = [up to date] testcommit1106 -> origin/testcommit1106
123 = [up to date] testcommit1107 -> origin/testcommit1107
124 = [up to date] testcommit1108 -> origin/testcommit1108
125 = [up to date] testcommit1109 -> origin/testcommit1109
126 = [up to date] testcommit111 -> origin/testcommit111
127 = [up to date] testcommit1110 -> origin/testcommit1110
128 = [up to date] testcommit1111 -> origin/testcommit1111
129 = [up to date] testcommit1112 -> origin/testcommit1112
130 = [up to date] testcommit1113 -> origin/testcommit1113
131 = [up to date] testcommit1114 -> origin/testcommit1114
132 = [up to date] testcommit1115 -> origin/testcommit1115
133 = [up to date] testcommit1116 -> origin/testcommit1116
134 = [up to date] testcommit1117 -> origin/testcommit1117
135 = [up to date] testcommit1118 -> origin/testcommit1118
136 = [up to date] testcommit1119 -> origin/testcommit1119
137 = [up to date] testcommit112 -> origin/testcommit112
138 = [up to date] testcommit1120 -> origin/testcommit1120
139 = [up to date] testcommit1121 -> origin/testcommit1121
140 = [up to date] testcommit1122 -> origin/testcommit1122
141 = [up to date] testcommit1123 -> origin/testcommit1123
142 = [up to date] testcommit1124 -> origin/testcommit1124
143 = [up to date] testcommit1125 -> origin/testcommit1125
144 = [up to date] testcommit1126 -> origin/testcommit1126
145 = [up to date] testcommit1127 -> origin/testcommit1127
146 = [up to date] testcommit1128 -> origin/testcommit1128
147 = [up to date] testcommit1129 -> origin/testcommit1129
148 = [up to date] testcommit113 -> origin/testcommit113
149 = [up to date] testcommit1130 -> origin/testcommit1130
150 = [up to date] testcommit1131 -> origin/testcommit1131
151 = [up to date] testcommit1132 -> origin/testcommit1132
152 = [up to date] testcommit1133 -> origin/testcommit1133
153 = [up to date] testcommit1134 -> origin/testcommit1134
154 = [up to date] testcommit1135 -> origin/testcommit1135
155 = [up to date] testcommit1136 -> origin/testcommit1136
156 = [up to date] testcommit1137 -> origin/testcommit1137
157 = [up to date] testcommit1138 -> origin/testcommit1138
158 = [up to date] testcommit1139 -> origin/testcommit1139
159 = [up to date] testcommit114 -> origin/testcommit114
160 = [up to date] testcommit1140 -> origin/testcommit1140
161 = [up to date] testcommit1141 -> origin/testcommit1141
162 = [up to date] testcommit1142 -> origin/testcommit1142
163 = [up to date] testcommit1143 -> origin/testcommit1143
164 = [up to date] testcommit1144 -> origin/testcommit1144
165 = [up to date] testcommit1145 -> origin/testcommit1145
166 = [up to date] testcommit1146 -> origin/testcommit1146
167 = [up to date] testcommit1147 -> origin/testcommit1147
168 = [up to date] testcommit1148 -> origin/testcommit1148
169 = [up to date] testcommit1149 -> origin/testcommit1149
170 = [up to date] testcommit115 -> origin/testcommit115
171 = [up to date] testcommit1150 -> origin/testcommit1150
172 = [up to date] testcommit1151 -> origin/testcommit1151
173 = [up to date] testcommit1152 -> origin/testcommit1152
174 = [up to date] testcommit1153 -> origin/testcommit1153
175 = [up to date] testcommit1154 -> origin/testcommit1154
176 = [up to date] testcommit1155 -> origin/testcommit1155
177 = [up to date] testcommit1156 -> origin/testcommit1156
178 = [up to date] testcommit1157 -> origin/testcommit1157
179 = [up to date] testcommit1158 -> origin/testcommit1158
180 = [up to date] testcommit1159 -> origin/testcommit1159
181 = [up to date] testcommit116 -> origin/testcommit116
182 = [up to date] testcommit1160 -> origin/testcommit1160
183 = [up to date] testcommit1161 -> origin/testcommit1161
184 = [up to date] testcommit1162 -> origin/testcommit1162
185 = [up to date] testcommit1163 -> origin/testcommit1163
186 = [up to date] testcommit1164 -> origin/testcommit1164
187 = [up to date] testcommit1165 -> origin/testcommit1165
188 = [up to date] testcommit1166 -> origin/testcommit1166
189 = [up to date] testcommit1167 -> origin/testcommit1167
190 = [up to date] testcommit1168 -> origin/testcommit1168
191 = [up to date] testcommit1169 -> origin/testcommit1169
192 = [up to date] testcommit117 -> origin/testcommit117
193 = [up to date] testcommit1170 -> origin/testcommit1170
194 = [up to date] testcommit1171 -> origin/testcommit1171
195 = [up to date] testcommit1172 -> origin/testcommit1172
196 = [up to date] testcommit1173 -> origin/testcommit1173
197 = [up to date] testcommit1174 -> origin/testcommit1174
198 = [up to date] testcommit1175 -> origin/testcommit1175
199 = [up to date] testcommit1176 -> origin/testcommit1176
200 = [up to date] testcommit1177 -> origin/testcommit1177
201 = [up to date] testcommit1178 -> origin/testcommit1178
202 = [up to date] testcommit1179 -> origin/testcommit1179
203 = [up to date] testcommit118 -> origin/testcommit118
204 = [up to date] testcommit1180 -> origin/testcommit1180
205 = [up to date] testcommit1181 -> origin/testcommit1181
206 = [up to date] testcommit1182 -> origin/testcommit1182
207 = [up to date] testcommit1183 -> origin/testcommit1183
208 = [up to date] testcommit1184 -> origin/testcommit1184
209 = [up to date] testcommit1185 -> origin/testcommit1185
210 = [up to date] testcommit1186 -> origin/testcommit1186
211 = [up to date] testcommit1187 -> origin/testcommit1187
212 = [up to date] testcommit1188 -> origin/testcommit1188
213 = [up to date] testcommit1189 -> origin/testcommit1189
214 = [up to date] testcommit119 -> origin/testcommit119
215 = [up to date] testcommit1190 -> origin/testcommit1190
216 = [up to date] testcommit1191 -> origin/testcommit1191
217 = [up to date] testcommit1192 -> origin/testcommit1192
218 = [up to date] testcommit1193 -> origin/testcommit1193
219 = [up to date] testcommit1194 -> origin/testcommit1194
220 = [up to date] testcommit1195 -> origin/testcommit1195
221 = [up to date] testcommit1196 -> origin/testcommit1196
222 = [up to date] testcommit1197 -> origin/testcommit1197
223 = [up to date] testcommit1198 -> origin/testcommit1198
224 = [up to date] testcommit1199 -> origin/testcommit1199
225 = [up to date] testcommit12 -> origin/testcommit12
226 = [up to date] testcommit120 -> origin/testcommit120
227 = [up to date] testcommit1200 -> origin/testcommit1200
228 = [up to date] testcommit1201 -> origin/testcommit1201
229 = [up to date] testcommit1202 -> origin/testcommit1202
230 = [up to date] testcommit1203 -> origin/testcommit1203
231 = [up to date] testcommit1204 -> origin/testcommit1204
232 = [up to date] testcommit1205 -> origin/testcommit1205
233 = [up to date] testcommit1206 -> origin/testcommit1206
234 = [up to date] testcommit1207 -> origin/testcommit1207
235 = [up to date] testcommit1208 -> origin/testcommit1208
236 = [up to date] testcommit1209 -> origin/testcommit1209
237 = [up to date] testcommit121 -> origin/testcommit121
238 = [up to date] testcommit1210 -> origin/testcommit1210
239 = [up to date] testcommit1211 -> origin/testcommit1211
240 = [up to date] testcommit1212 -> origin/testcommit1212
241 = [up to date] testcommit1213 -> origin/testcommit1213
242 = [up to date] testcommit1214 -> origin/testcommit1214
243 = [up to date] testcommit1215 -> origin/testcommit1215
244 = [up to date] testcommit1216 -> origin/testcommit1216
245 = [up to date] testcommit1217 -> origin/testcommit1217
246 = [up to date] testcommit1218 -> origin/testcommit1218
247 = [up to date] testcommit1219 -> origin/testcommit1219
248 = [up to date] testcommit122 -> origin/testcommit122
249 = [up to date] testcommit1220 -> origin/testcommit1220
250 = [up to date] testcommit1221 -> origin/testcommit1221
251 = [up to date] testcommit1222 -> origin/testcommit1222
252 = [up to date] testcommit1223 -> origin/testcommit1223
253 = [up to date] testcommit1224 -> origin/testcommit1224
254 = [up to date] testcommit1225 -> origin/testcommit1225
255 = [up to date] testcommit1226 -> origin/testcommit1226
256 = [up to date] testcommit1227 -> origin/testcommit1227
257 = [up to date] testcommit1228 -> origin/testcommit1228
258 = [up to date] testcommit1229 -> origin/testcommit1229
259 = [up to date] testcommit123 -> origin/testcommit123
260 = [up to date] testcommit1230 -> origin/testcommit1230
261 = [up to date] testcommit1231 -> origin/testcommit1231
262 = [up to date] testcommit1232 -> origin/testcommit1232
263 = [up to date] testcommit1233 -> origin/testcommit1233
264 = [up to date] testcommit1234 -> origin/testcommit1234
265 = [up to date] testcommit1235 -> origin/testcommit1235
266 = [up to date] testcommit1236 -> origin/testcommit1236
267 = [up to date] testcommit1237 -> origin/testcommit1237
268 = [up to date] testcommit1238 -> origin/testcommit1238
269 = [up to date] testcommit1239 -> origin/testcommit1239
270 = [up to date] testcommit124 -> origin/testcommit124
271 = [up to date] testcommit1240 -> origin/testcommit1240
272 = [up to date] testcommit1241 -> origin/testcommit1241
273 = [up to date] testcommit1242 -> origin/testcommit1242
274 = [up to date] testcommit1243 -> origin/testcommit1243
275 = [up to date] testcommit1244 -> origin/testcommit1244
276 = [up to date] testcommit1245 -> origin/testcommit1245
277 = [up to date] testcommit1246 -> origin/testcommit1246
278 = [up to date] testcommit1247 -> origin/testcommit1247
279 = [up to date] testcommit1248 -> origin/testcommit1248
280 = [up to date] testcommit1249 -> origin/testcommit1249
281 = [up to date] testcommit125 -> origin/testcommit125
282 = [up to date] testcommit1250 -> origin/testcommit1250
283 = [up to date] testcommit1251 -> origin/testcommit1251
284 = [up to date] testcommit1252 -> origin/testcommit1252
285 = [up to date] testcommit1253 -> origin/testcommit1253
286 = [up to date] testcommit1254 -> origin/testcommit1254
287 = [up to date] testcommit1255 -> origin/testcommit1255
288 = [up to date] testcommit1256 -> origin/testcommit1256
289 = [up to date] testcommit1257 -> origin/testcommit1257
290 = [up to date] testcommit1258 -> origin/testcommit1258
291 = [up to date] testcommit1259 -> origin/testcommit1259
292 = [up to date] testcommit126 -> origin/testcommit126
293 = [up to date] testcommit1260 -> origin/testcommit1260
294 = [up to date] testcommit1261 -> origin/testcommit1261
295 = [up to date] testcommit1262 -> origin/testcommit1262
296 = [up to date] testcommit1263 -> origin/testcommit1263
297 = [up to date] testcommit1264 -> origin/testcommit1264
298 = [up to date] testcommit1265 -> origin/testcommit1265
299 = [up to date] testcommit1266 -> origin/testcommit1266
300 = [up to date] testcommit1267 -> origin/testcommit1267
301 = [up to date] testcommit1268 -> origin/testcommit1268
302 = [up to date] testcommit1269 -> origin/testcommit1269
303 = [up to date] testcommit127 -> origin/testcommit127
304 = [up to date] testcommit1270 -> origin/testcommit1270
305 = [up to date] testcommit1271 -> origin/testcommit1271
306 = [up to date] testcommit1272 -> origin/testcommit1272
307 = [up to date] testcommit1273 -> origin/testcommit1273
308 = [up to date] testcommit1274 -> origin/testcommit1274
309 = [up to date] testcommit1275 -> origin/testcommit1275
310 = [up to date] testcommit1276 -> origin/testcommit1276
311 = [up to date] testcommit1277 -> origin/testcommit1277
312 = [up to date] testcommit1278 -> origin/testcommit1278
313 = [up to date] testcommit1279 -> origin/testcommit1279
314 = [up to date] testcommit128 -> origin/testcommit128
315 = [up to date] testcommit1280 -> origin/testcommit1280
316 = [up to date] testcommit1281 -> origin/testcommit1281
317 = [up to date] testcommit1282 -> origin/testcommit1282
318 = [up to date] testcommit1283 -> origin/testcommit1283
319 = [up to date] testcommit1284 -> origin/testcommit1284
320 = [up to date] testcommit1285 -> origin/testcommit1285
321 = [up to date] testcommit1286 -> origin/testcommit1286
322 = [up to date] testcommit1287 -> origin/testcommit1287
323 = [up to date] testcommit1288 -> origin/testcommit1288
324 = [up to date] testcommit1289 -> origin/testcommit1289
325 = [up to date] testcommit129 -> origin/testcommit129
326 = [up to date] testcommit1290 -> origin/testcommit1290
327 = [up to date] testcommit1291 -> origin/testcommit1291
328 = [up to date] testcommit1292 -> origin/testcommit1292
329 = [up to date] testcommit1293 -> origin/testcommit1293
330 = [up to date] testcommit1294 -> origin/testcommit1294
331 = [up to date] testcommit1295 -> origin/testcommit1295
332 = [up to date] testcommit1296 -> origin/testcommit1296
333 = [up to date] testcommit1297 -> origin/testcommit1297
334 = [up to date] testcommit1298 -> origin/testcommit1298
335 = [up to date] testcommit1299 -> origin/testcommit1299
336 = [up to date] testcommit13 -> origin/testcommit13
337 = [up to date] testcommit130 -> origin/testcommit130
338 = [up to date] testcommit1300 -> origin/testcommit1300
339 = [up to date] testcommit1301 -> origin/testcommit1301
340 = [up to date] testcommit1302 -> origin/testcommit1302
341 = [up to date] testcommit1303 -> origin/testcommit1303
342 = [up to date] testcommit1304 -> origin/testcommit1304
343 = [up to date] testcommit1305 -> origin/testcommit1305
344 = [up to date] testcommit1306 -> origin/testcommit1306
345 = [up to date] testcommit1307 -> origin/testcommit1307
346 = [up to date] testcommit1308 -> origin/testcommit1308
347 = [up to date] testcommit1309 -> origin/testcommit1309
348 = [up to date] testcommit131 -> origin/testcommit131
349 = [up to date] testcommit1310 -> origin/testcommit1310
350 = [up to date] testcommit1311 -> origin/testcommit1311
351 = [up to date] testcommit1312 -> origin/testcommit1312
352 = [up to date] testcommit1313 -> origin/testcommit1313
353 = [up to date] testcommit1314 -> origin/testcommit1314
354 = [up to date] testcommit1315 -> origin/testcommit1315
355 = [up to date] testcommit1316 -> origin/testcommit1316
356 = [up to date] testcommit1317 -> origin/testcommit1317
357 = [up to date] testcommit1318 -> origin/testcommit1318
358 = [up to date] testcommit1319 -> origin/testcommit1319
359 = [up to date] testcommit132 -> origin/testcommit132
360 = [up to date] testcommit1320 -> origin/testcommit1320
361 = [up to date] testcommit1321 -> origin/testcommit1321
362 = [up to date] testcommit1322 -> origin/testcommit1322
363 = [up to date] testcommit1323 -> origin/testcommit1323
364 = [up to date] testcommit1324 -> origin/testcommit1324
365 = [up to date] testcommit1325 -> origin/testcommit1325
366 = [up to date] testcommit1326 -> origin/testcommit1326
367 = [up to date] testcommit1327 -> origin/testcommit1327
368 = [up to date] testcommit1328 -> origin/testcommit1328
369 = [up to date] testcommit1329 -> origin/testcommit1329
370 = [up to date] testcommit133 -> origin/testcommit133
371 = [up to date] testcommit1330 -> origin/testcommit1330
372 = [up to date] testcommit1331 -> origin/testcommit1331
373 = [up to date] testcommit1332 -> origin/testcommit1332
374 = [up to date] testcommit1333 -> origin/testcommit1333
375 = [up to date] testcommit1334 -> origin/testcommit1334
376 = [up to date] testcommit1335 -> origin/testcommit1335
377 = [up to date] testcommit1336 -> origin/testcommit1336
378 = [up to date] testcommit1337 -> origin/testcommit1337
379 = [up to date] testcommit1338 -> origin/testcommit1338
380 = [up to date] testcommit1339 -> origin/testcommit1339
381 = [up to date] testcommit134 -> origin/testcommit134
382 = [up to date] testcommit1340 -> origin/testcommit1340
383 = [up to date] testcommit1341 -> origin/testcommit1341
384 = [up to date] testcommit1342 -> origin/testcommit1342
385 = [up to date] testcommit1343 -> origin/testcommit1343
386 = [up to date] testcommit1344 -> origin/testcommit1344
387 = [up to date] testcommit1345 -> origin/testcommit1345
388 = [up to date] testcommit1346 -> origin/testcommit1346
389 = [up to date] testcommit1347 -> origin/testcommit1347
390 = [up to date] testcommit1348 -> origin/testcommit1348
391 = [up to date] testcommit1349 -> origin/testcommit1349
392 = [up to date] testcommit135 -> origin/testcommit135
393 = [up to date] testcommit1350 -> origin/testcommit1350
394 = [up to date] testcommit1351 -> origin/testcommit1351
395 = [up to date] testcommit1352 -> origin/testcommit1352
396 = [up to date] testcommit1353 -> origin/testcommit1353
397 = [up to date] testcommit1354 -> origin/testcommit1354
398 = [up to date] testcommit1355 -> origin/testcommit1355
399 = [up to date] testcommit1356 -> origin/testcommit1356
400 = [up to date] testcommit1357 -> origin/testcommit1357
401 = [up to date] testcommit1358 -> origin/testcommit1358
402 = [up to date] testcommit1359 -> origin/testcommit1359
403 = [up to date] testcommit136 -> origin/testcommit136
404 = [up to date] testcommit1360 -> origin/testcommit1360
405 = [up to date] testcommit1361 -> origin/testcommit1361
406 = [up to date] testcommit1362 -> origin/testcommit1362
407 = [up to date] testcommit1363 -> origin/testcommit1363
408 = [up to date] testcommit1364 -> origin/testcommit1364
409 = [up to date] testcommit1365 -> origin/testcommit1365
410 = [up to date] testcommit1366 -> origin/testcommit1366
411 = [up to date] testcommit1367 -> origin/testcommit1367
412 = [up to date] testcommit1368 -> origin/testcommit1368
413 = [up to date] testcommit1369 -> origin/testcommit1369
414 = [up to date] testcommit137 -> origin/testcommit137
415 = [up to date] testcommit1370 -> origin/testcommit1370
416 = [up to date] testcommit1371 -> origin/testcommit1371
417 = [up to date] testcommit1372 -> origin/testcommit1372
418 = [up to date] testcommit1373 -> origin/testcommit1373
419 = [up to date] testcommit1374 -> origin/testcommit1374
420 = [up to date] testcommit1375 -> origin/testcommit1375
421 = [up to date] testcommit1376 -> origin/testcommit1376
422 = [up to date] testcommit1377 -> origin/testcommit1377
423 = [up to date] testcommit1378 -> origin/testcommit1378
424 = [up to date] testcommit1379 -> origin/testcommit1379
425 = [up to date] testcommit138 -> origin/testcommit138
426 = [up to date] testcommit1380 -> origin/testcommit1380
427 = [up to date] testcommit1381 -> origin/testcommit1381
428 = [up to date] testcommit1382 -> origin/testcommit1382
429 = [up to date] testcommit1383 -> origin/testcommit1383
430 = [up to date] testcommit1384 -> origin/testcommit1384
431 = [up to date] testcommit1385 -> origin/testcommit1385
432 = [up to date] testcommit1386 -> origin/testcommit1386
433 = [up to date] testcommit1387 -> origin/testcommit1387
434 = [up to date] testcommit1388 -> origin/testcommit1388
435 = [up to date] testcommit1389 -> origin/testcommit1389
436 = [up to date] testcommit139 -> origin/testcommit139
437 = [up to date] testcommit1390 -> origin/testcommit1390
438 = [up to date] testcommit1391 -> origin/testcommit1391
439 = [up to date] testcommit1392 -> origin/testcommit1392
440 = [up to date] testcommit1393 -> origin/testcommit1393
441 = [up to date] testcommit1394 -> origin/testcommit1394
442 = [up to date] testcommit1395 -> origin/testcommit1395
443 = [up to date] testcommit1396 -> origin/testcommit1396
444 = [up to date] testcommit1397 -> origin/testcommit1397
445 = [up to date] testcommit1398 -> origin/testcommit1398
446 = [up to date] testcommit1399 -> origin/testcommit1399
447 = [up to date] testcommit14 -> origin/testcommit14
448 = [up to date] testcommit140 -> origin/testcommit140
449 = [up to date] testcommit1400 -> origin/testcommit1400
450 = [up to date] testcommit1401 -> origin/testcommit1401
451 = [up to date] testcommit1402 -> origin/testcommit1402
452 = [up to date] testcommit1403 -> origin/testcommit1403
453 = [up to date] testcommit1404 -> origin/testcommit1404
454 = [up to date] testcommit1405 -> origin/testcommit1405
455 = [up to date] testcommit1406 -> origin/testcommit1406
456 = [up to date] testcommit1407 -> origin/testcommit1407
457 = [up to date] testcommit1408 -> origin/testcommit1408
458 = [up to date] testcommit1409 -> origin/testcommit1409
459 = [up to date] testcommit141 -> origin/testcommit141
460 = [up to date] testcommit1410 -> origin/testcommit1410
461 = [up to date] testcommit1411 -> origin/testcommit1411
462 = [up to date] testcommit1412 -> origin/testcommit1412
463 = [up to date] testcommit1413 -> origin/testcommit1413
464 = [up to date] testcommit1414 -> origin/testcommit1414
465 = [up to date] testcommit1415 -> origin/testcommit1415
466 = [up to date] testcommit1416 -> origin/testcommit1416
467 = [up to date] testcommit1417 -> origin/testcommit1417
468 = [up to date] testcommit1418 -> origin/testcommit1418
469 = [up to date] testcommit1419 -> origin/testcommit1419
470 = [up to date] testcommit142 -> origin/testcommit142
471 = [up to date] testcommit1420 -> origin/testcommit1420
472 = [up to date] testcommit1421 -> origin/testcommit1421
473 = [up to date] testcommit1422 -> origin/testcommit1422
474 = [up to date] testcommit1423 -> origin/testcommit1423
475 = [up to date] testcommit1424 -> origin/testcommit1424
476 = [up to date] testcommit1425 -> origin/testcommit1425
477 = [up to date] testcommit1426 -> origin/testcommit1426
478 = [up to date] testcommit1427 -> origin/testcommit1427
479 = [up to date] testcommit1428 -> origin/testcommit1428
480 = [up to date] testcommit1429 -> origin/testcommit1429
481 = [up to date] testcommit143 -> origin/testcommit143
482 = [up to date] testcommit1430 -> origin/testcommit1430
483 = [up to date] testcommit1431 -> origin/testcommit1431
484 = [up to date] testcommit1432 -> origin/testcommit1432
485 = [up to date] testcommit1433 -> origin/testcommit1433
486 = [up to date] testcommit1434 -> origin/testcommit1434
487 = [up to date] testcommit1435 -> origin/testcommit1435
488 = [up to date] testcommit1436 -> origin/testcommit1436
489 = [up to date] testcommit1437 -> origin/testcommit1437
490 = [up to date] testcommit1438 -> origin/testcommit1438
491 = [up to date] testcommit1439 -> origin/testcommit1439
492 = [up to date] testcommit144 -> origin/testcommit144
493 = [up to date] testcommit1440 -> origin/testcommit1440
494 = [up to date] testcommit1441 -> origin/testcommit1441
495 = [up to date] testcommit1442 -> origin/testcommit1442
496 = [up to date] testcommit1443 -> origin/testcommit1443
497 = [up to date] testcommit1444 -> origin/testcommit1444
498 = [up to date] testcommit1445 -> origin/testcommit1445
499 = [up to date] testcommit1446 -> origin/testcommit1446
500 = [up to date] testcommit1447 -> origin/testcommit1447
501 = [up to date] testcommit1448 -> origin/testcommit1448
502 = [up to date] testcommit1449 -> origin/testcommit1449
503 = [up to date] testcommit145 -> origin/testcommit145
504 = [up to date] testcommit1450 -> origin/testcommit1450
505 = [up to date] testcommit1451 -> origin/testcommit1451
506 = [up to date] testcommit1452 -> origin/testcommit1452
507 = [up to date] testcommit1453 -> origin/testcommit1453
508 = [up to date] testcommit1454 -> origin/testcommit1454
509 = [up to date] testcommit1455 -> origin/testcommit1455
510 = [up to date] testcommit1456 -> origin/testcommit1456
511 = [up to date] testcommit1457 -> origin/testcommit1457
512 = [up to date] testcommit1458 -> origin/testcommit1458
513 = [up to date] testcommit1459 -> origin/testcommit1459
514 = [up to date] testcommit146 -> origin/testcommit146
515 = [up to date] testcommit1460 -> origin/testcommit1460
516 = [up to date] testcommit1461 -> origin/testcommit1461
517 = [up to date] testcommit1462 -> origin/testcommit1462
518 = [up to date] testcommit1463 -> origin/testcommit1463
519 = [up to date] testcommit1464 -> origin/testcommit1464
520 = [up to date] testcommit1465 -> origin/testcommit1465
521 = [up to date] testcommit1466 -> origin/testcommit1466
522 = [up to date] testcommit1467 -> origin/testcommit1467
523 = [up to date] testcommit1468 -> origin/testcommit1468
524 = [up to date] testcommit1469 -> origin/testcommit1469
525 = [up to date] testcommit147 -> origin/testcommit147
526 = [up to date] testcommit1470 -> origin/testcommit1470
527 = [up to date] testcommit1471 -> origin/testcommit1471
528 = [up to date] testcommit1472 -> origin/testcommit1472
529 = [up to date] testcommit1473 -> origin/testcommit1473
530 = [up to date] testcommit1474 -> origin/testcommit1474
531 = [up to date] testcommit1475 -> origin/testcommit1475
532 = [up to date] testcommit1476 -> origin/testcommit1476
533 = [up to date] testcommit1477 -> origin/testcommit1477
534 = [up to date] testcommit1478 -> origin/testcommit1478
535 = [up to date] testcommit1479 -> origin/testcommit1479
536 = [up to date] testcommit148 -> origin/testcommit148
537 = [up to date] testcommit1480 -> origin/testcommit1480
538 = [up to date] testcommit1481 -> origin/testcommit1481
539 = [up to date] testcommit1482 -> origin/testcommit1482
540 = [up to date] testcommit1483 -> origin/testcommit1483
541 = [up to date] testcommit1484 -> origin/testcommit1484
542 = [up to date] testcommit1485 -> origin/testcommit1485
543 = [up to date] testcommit1486 -> origin/testcommit1486
544 = [up to date] testcommit1487 -> origin/testcommit1487
545 = [up to date] testcommit1488 -> origin/testcommit1488
546 = [up to date] testcommit1489 -> origin/testcommit1489
547 = [up to date] testcommit149 -> origin/testcommit149
548 = [up to date] testcommit1490 -> origin/testcommit1490
549 = [up to date] testcommit1491 -> origin/testcommit1491
550 = [up to date] testcommit1492 -> origin/testcommit1492
551 = [up to date] testcommit1493 -> origin/testcommit1493
552 = [up to date] testcommit1494 -> origin/testcommit1494
553 = [up to date] testcommit1495 -> origin/testcommit1495
554 = [up to date] testcommit1496 -> origin/testcommit1496
555 = [up to date] testcommit1497 -> origin/testcommit1497
556 = [up to date] testcommit1498 -> origin/testcommit1498
557 = [up to date] testcommit1499 -> origin/testcommit1499
558 = [up to date] testcommit15 -> origin/testcommit15
559 = [up to date] testcommit150 -> origin/testcommit150
560 = [up to date] testcommit1500 -> origin/testcommit1500
561 = [up to date] testcommit1501 -> origin/testcommit1501
562 = [up to date] testcommit1502 -> origin/testcommit1502
563 = [up to date] testcommit1503 -> origin/testcommit1503
564 = [up to date] testcommit1504 -> origin/testcommit1504
565 = [up to date] testcommit1505 -> origin/testcommit1505
566 = [up to date] testcommit1506 -> origin/testcommit1506
567 = [up to date] testcommit1507 -> origin/testcommit1507
568 = [up to date] testcommit1508 -> origin/testcommit1508
569 = [up to date] testcommit1509 -> origin/testcommit1509
570 = [up to date] testcommit151 -> origin/testcommit151
571 = [up to date] testcommit1510 -> origin/testcommit1510
572 = [up to date] testcommit1511 -> origin/testcommit1511
573 = [up to date] testcommit1512 -> origin/testcommit1512
574 = [up to date] testcommit1513 -> origin/testcommit1513
575 = [up to date] testcommit1514 -> origin/testcommit1514
576 = [up to date] testcommit1515 -> origin/testcommit1515
577 = [up to date] testcommit1516 -> origin/testcommit1516
578 = [up to date] testcommit1517 -> origin/testcommit1517
579 = [up to date] testcommit1518 -> origin/testcommit1518
580 = [up to date] testcommit1519 -> origin/testcommit1519
581 = [up to date] testcommit152 -> origin/testcommit152
582 = [up to date] testcommit1520 -> origin/testcommit1520
583 = [up to date] testcommit1521 -> origin/testcommit1521
584 = [up to date] testcommit1522 -> origin/testcommit1522
585 = [up to date] testcommit1523 -> origin/testcommit1523
586 = [up to date] testcommit1524 -> origin/testcommit1524
587 = [up to date] testcommit1525 -> origin/testcommit1525
588 = [up to date] testcommit1526 -> origin/testcommit1526
589 = [up to date] testcommit1527 -> origin/testcommit1527
590 = [up to date] testcommit1528 -> origin/testcommit1528
591 = [up to date] testcommit1529 -> origin/testcommit1529
592 = [up to date] testcommit153 -> origin/testcommit153
593 = [up to date] testcommit1530 -> origin/testcommit1530
594 = [up to date] testcommit1531 -> origin/testcommit1531
595 = [up to date] testcommit1532 -> origin/testcommit1532
596 = [up to date] testcommit1533 -> origin/testcommit1533
597 = [up to date] testcommit1534 -> origin/testcommit1534
598 = [up to date] testcommit1535 -> origin/testcommit1535
599 = [up to date] testcommit1536 -> origin/testcommit1536
600 = [up to date] testcommit1537 -> origin/testcommit1537
601 = [up to date] testcommit1538 -> origin/testcommit1538
602 = [up to date] testcommit1539 -> origin/testcommit1539
603 = [up to date] testcommit154 -> origin/testcommit154
604 = [up to date] testcommit1540 -> origin/testcommit1540
605 = [up to date] testcommit1541 -> origin/testcommit1541
606 = [up to date] testcommit1542 -> origin/testcommit1542
607 = [up to date] testcommit1543 -> origin/testcommit1543
608 = [up to date] testcommit1544 -> origin/testcommit1544
609 = [up to date] testcommit1545 -> origin/testcommit1545
610 = [up to date] testcommit1546 -> origin/testcommit1546
611 = [up to date] testcommit1547 -> origin/testcommit1547
612 = [up to date] testcommit1548 -> origin/testcommit1548
613 = [up to date] testcommit1549 -> origin/testcommit1549
614 = [up to date] testcommit155 -> origin/testcommit155
615 = [up to date] testcommit1550 -> origin/testcommit1550
616 = [up to date] testcommit1551 -> origin/testcommit1551
617 = [up to date] testcommit1552 -> origin/testcommit1552
618 = [up to date] testcommit1553 -> origin/testcommit1553
619 = [up to date] testcommit1554 -> origin/testcommit1554
620 = [up to date] testcommit1555 -> origin/testcommit1555
621 = [up to date] testcommit1556 -> origin/testcommit1556
622 = [up to date] testcommit1557 -> origin/testcommit1557
623 = [up to date] testcommit1558 -> origin/testcommit1558
624 = [up to date] testcommit1559 -> origin/testcommit1559
625 = [up to date] testcommit156 -> origin/testcommit156
626 = [up to date] testcommit1560 -> origin/testcommit1560
627 = [up to date] testcommit1561 -> origin/testcommit1561
628 = [up to date] testcommit1562 -> origin/testcommit1562
629 = [up to date] testcommit1563 -> origin/testcommit1563
630 = [up to date] testcommit1564 -> origin/testcommit1564
631 = [up to date] testcommit1565 -> origin/testcommit1565
632 = [up to date] testcommit1566 -> origin/testcommit1566
633 = [up to date] testcommit1567 -> origin/testcommit1567
634 = [up to date] testcommit1568 -> origin/testcommit1568
635 = [up to date] testcommit1569 -> origin/testcommit1569
636 = [up to date] testcommit157 -> origin/testcommit157
637 = [up to date] testcommit1570 -> origin/testcommit1570
638 = [up to date] testcommit1571 -> origin/testcommit1571
639 = [up to date] testcommit1572 -> origin/testcommit1572
640 = [up to date] testcommit1573 -> origin/testcommit1573
641 = [up to date] testcommit1574 -> origin/testcommit1574
642 = [up to date] testcommit1575 -> origin/testcommit1575
643 = [up to date] testcommit1576 -> origin/testcommit1576
644 = [up to date] testcommit1577 -> origin/testcommit1577
645 = [up to date] testcommit1578 -> origin/testcommit1578
646 = [up to date] testcommit1579 -> origin/testcommit1579
647 = [up to date] testcommit158 -> origin/testcommit158
648 = [up to date] testcommit1580 -> origin/testcommit1580
649 = [up to date] testcommit1581 -> origin/testcommit1581
650 = [up to date] testcommit1582 -> origin/testcommit1582
651 = [up to date] testcommit1583 -> origin/testcommit1583
652 = [up to date] testcommit1584 -> origin/testcommit1584
653 = [up to date] testcommit1585 -> origin/testcommit1585
654 = [up to date] testcommit1586 -> origin/testcommit1586
655 = [up to date] testcommit1587 -> origin/testcommit1587
656 = [up to date] testcommit1588 -> origin/testcommit1588
657 = [up to date] testcommit1589 -> origin/testcommit1589
658 = [up to date] testcommit159 -> origin/testcommit159
659 = [up to date] testcommit1590 -> origin/testcommit1590
660 = [up to date] testcommit1591 -> origin/testcommit1591
661 = [up to date] testcommit1592 -> origin/testcommit1592
662 = [up to date] testcommit1593 -> origin/testcommit1593
663 = [up to date] testcommit1594 -> origin/testcommit1594
664 = [up to date] testcommit1595 -> origin/testcommit1595
665 = [up to date] testcommit1596 -> origin/testcommit1596
666 = [up to date] testcommit1597 -> origin/testcommit1597
667 = [up to date] testcommit1598 -> origin/testcommit1598
668 = [up to date] testcommit1599 -> origin/testcommit1599
669 = [up to date] testcommit16 -> origin/testcommit16
670 = [up to date] testcommit160 -> origin/testcommit160
671 = [up to date] testcommit1600 -> origin/testcommit1600
672 = [up to date] testcommit1601 -> origin/testcommit1601
673 = [up to date] testcommit1602 -> origin/testcommit1602
674 = [up to date] testcommit1603 -> origin/testcommit1603
675 = [up to date] testcommit1604 -> origin/testcommit1604
676 = [up to date] testcommit1605 -> origin/testcommit1605
677 = [up to date] testcommit1606 -> origin/testcommit1606
678 = [up to date] testcommit1607 -> origin/testcommit1607
679 = [up to date] testcommit1608 -> origin/testcommit1608
680 = [up to date] testcommit1609 -> origin/testcommit1609
681 = [up to date] testcommit161 -> origin/testcommit161
682 = [up to date] testcommit1610 -> origin/testcommit1610
683 = [up to date] testcommit1611 -> origin/testcommit1611
684 = [up to date] testcommit1612 -> origin/testcommit1612
685 = [up to date] testcommit1613 -> origin/testcommit1613
686 = [up to date] testcommit1614 -> origin/testcommit1614
687 = [up to date] testcommit1615 -> origin/testcommit1615
688 = [up to date] testcommit1616 -> origin/testcommit1616
689 = [up to date] testcommit1617 -> origin/testcommit1617
690 = [up to date] testcommit1618 -> origin/testcommit1618
691 = [up to date] testcommit1619 -> origin/testcommit1619
692 = [up to date] testcommit162 -> origin/testcommit162
693 = [up to date] testcommit1620 -> origin/testcommit1620
694 = [up to date] testcommit1621 -> origin/testcommit1621
695 = [up to date] testcommit1622 -> origin/testcommit1622
696 = [up to date] testcommit1623 -> origin/testcommit1623
697 = [up to date] testcommit1624 -> origin/testcommit1624
698 = [up to date] testcommit1625 -> origin/testcommit1625
699 = [up to date] testcommit1626 -> origin/testcommit1626
700 = [up to date] testcommit1627 -> origin/testcommit1627
701 = [up to date] testcommit1628 -> origin/testcommit1628
702 = [up to date] testcommit1629 -> origin/testcommit1629
703 = [up to date] testcommit163 -> origin/testcommit163
704 = [up to date] testcommit1630 -> origin/testcommit1630
705 = [up to date] testcommit1631 -> origin/testcommit1631
706 = [up to date] testcommit1632 -> origin/testcommit1632
707 = [up to date] testcommit1633 -> origin/testcommit1633
708 = [up to date] testcommit1634 -> origin/testcommit1634
709 = [up to date] testcommit1635 -> origin/testcommit1635
710 = [up to date] testcommit1636 -> origin/testcommit1636
711 = [up to date] testcommit1637 -> origin/testcommit1637
712 = [up to date] testcommit1638 -> origin/testcommit1638
713 = [up to date] testcommit1639 -> origin/testcommit1639
714 = [up to date] testcommit164 -> origin/testcommit164
715 = [up to date] testcommit1640 -> origin/testcommit1640
716 = [up to date] testcommit1641 -> origin/testcommit1641
717 = [up to date] testcommit1642 -> origin/testcommit1642
718 = [up to date] testcommit1643 -> origin/testcommit1643
719 = [up to date] testcommit1644 -> origin/testcommit1644
720 = [up to date] testcommit1645 -> origin/testcommit1645
721 = [up to date] testcommit1646 -> origin/testcommit1646
722 = [up to date] testcommit1647 -> origin/testcommit1647
723 = [up to date] testcommit1648 -> origin/testcommit1648
724 = [up to date] testcommit1649 -> origin/testcommit1649
725 = [up to date] testcommit165 -> origin/testcommit165
726 = [up to date] testcommit1650 -> origin/testcommit1650
727 = [up to date] testcommit1651 -> origin/testcommit1651
728 = [up to date] testcommit1652 -> origin/testcommit1652
729 = [up to date] testcommit1653 -> origin/testcommit1653
730 = [up to date] testcommit1654 -> origin/testcommit1654
731 = [up to date] testcommit1655 -> origin/testcommit1655
732 = [up to date] testcommit1656 -> origin/testcommit1656
733 = [up to date] testcommit1657 -> origin/testcommit1657
734 = [up to date] testcommit1658 -> origin/testcommit1658
735 = [up to date] testcommit1659 -> origin/testcommit1659
736 = [up to date] testcommit166 -> origin/testcommit166
737 = [up to date] testcommit1660 -> origin/testcommit1660
738 = [up to date] testcommit1661 -> origin/testcommit1661
739 = [up to date] testcommit1662 -> origin/testcommit1662
740 = [up to date] testcommit1663 -> origin/testcommit1663
741 = [up to date] testcommit1664 -> origin/testcommit1664
742 = [up to date] testcommit1665 -> origin/testcommit1665
743 = [up to date] testcommit1666 -> origin/testcommit1666
744 = [up to date] testcommit1667 -> origin/testcommit1667
745 = [up to date] testcommit1668 -> origin/testcommit1668
746 = [up to date] testcommit1669 -> origin/testcommit1669
747 = [up to date] testcommit167 -> origin/testcommit167
748 = [up to date] testcommit1670 -> origin/testcommit1670
749 = [up to date] testcommit1671 -> origin/testcommit1671
750 = [up to date] testcommit1672 -> origin/testcommit1672
751 = [up to date] testcommit1673 -> origin/testcommit1673
752 = [up to date] testcommit1674 -> origin/testcommit1674
753 = [up to date] testcommit1675 -> origin/testcommit1675
754 = [up to date] testcommit1676 -> origin/testcommit1676
755 = [up to date] testcommit1677 -> origin/testcommit1677
756 = [up to date] testcommit1678 -> origin/testcommit1678
757 = [up to date] testcommit1679 -> origin/testcommit1679
758 = [up to date] testcommit168 -> origin/testcommit168
759 = [up to date] testcommit1680 -> origin/testcommit1680
760 = [up to date] testcommit1681 -> origin/testcommit1681
761 = [up to date] testcommit1682 -> origin/testcommit1682
762 = [up to date] testcommit1683 -> origin/testcommit1683
763 = [up to date] testcommit1684 -> origin/testcommit1684
764 = [up to date] testcommit1685 -> origin/testcommit1685
765 = [up to date] testcommit1686 -> origin/testcommit1686
766 = [up to date] testcommit1687 -> origin/testcommit1687
767 = [up to date] testcommit1688 -> origin/testcommit1688
768 = [up to date] testcommit1689 -> origin/testcommit1689
769 = [up to date] testcommit169 -> origin/testcommit169
770 = [up to date] testcommit1690 -> origin/testcommit1690
771 = [up to date] testcommit1691 -> origin/testcommit1691
772 = [up to date] testcommit1692 -> origin/testcommit1692
773 = [up to date] testcommit1693 -> origin/testcommit1693
774 = [up to date] testcommit1694 -> origin/testcommit1694
775 = [up to date] testcommit1695 -> origin/testcommit1695
776 = [up to date] testcommit1696 -> origin/testcommit1696
777 = [up to date] testcommit1697 -> origin/testcommit1697
778 = [up to date] testcommit1698 -> origin/testcommit1698
779 = [up to date] testcommit1699 -> origin/testcommit1699
780 = [up to date] testcommit17 -> origin/testcommit17
781 = [up to date] testcommit170 -> origin/testcommit170
782 = [up to date] testcommit1700 -> origin/testcommit1700
783 = [up to date] testcommit1701 -> origin/testcommit1701
784 = [up to date] testcommit1702 -> origin/testcommit1702
785 = [up to date] testcommit1703 -> origin/testcommit1703
786 = [up to date] testcommit1704 -> origin/testcommit1704
787 = [up to date] testcommit1705 -> origin/testcommit1705
788 = [up to date] testcommit1706 -> origin/testcommit1706
789 = [up to date] testcommit1707 -> origin/testcommit1707
790 = [up to date] testcommit1708 -> origin/testcommit1708
791 = [up to date] testcommit1709 -> origin/testcommit1709
792 = [up to date] testcommit171 -> origin/testcommit171
793 = [up to date] testcommit1710 -> origin/testcommit1710
794 = [up to date] testcommit1711 -> origin/testcommit1711
795 = [up to date] testcommit1712 -> origin/testcommit1712
796 = [up to date] testcommit1713 -> origin/testcommit1713
797 = [up to date] testcommit1714 -> origin/testcommit1714
798 = [up to date] testcommit1715 -> origin/testcommit1715
799 = [up to date] testcommit1716 -> origin/testcommit1716
800 = [up to date] testcommit1717 -> origin/testcommit1717
801 = [up to date] testcommit1718 -> origin/testcommit1718
802 = [up to date] testcommit1719 -> origin/testcommit1719
803 = [up to date] testcommit172 -> origin/testcommit172
804 = [up to date] testcommit1720 -> origin/testcommit1720
805 = [up to date] testcommit1721 -> origin/testcommit1721
806 = [up to date] testcommit1722 -> origin/testcommit1722
807 = [up to date] testcommit1723 -> origin/testcommit1723
808 = [up to date] testcommit1724 -> origin/testcommit1724
809 = [up to date] testcommit1725 -> origin/testcommit1725
810 = [up to date] testcommit1726 -> origin/testcommit1726
811 = [up to date] testcommit1727 -> origin/testcommit1727
812 = [up to date] testcommit1728 -> origin/testcommit1728
813 = [up to date] testcommit1729 -> origin/testcommit1729
814 = [up to date] testcommit173 -> origin/testcommit173
815 = [up to date] testcommit1730 -> origin/testcommit1730
816 = [up to date] testcommit1731 -> origin/testcommit1731
817 = [up to date] testcommit1732 -> origin/testcommit1732
818 = [up to date] testcommit1733 -> origin/testcommit1733
819 = [up to date] testcommit1734 -> origin/testcommit1734
820 = [up to date] testcommit1735 -> origin/testcommit1735
821 = [up to date] testcommit1736 -> origin/testcommit1736
822 = [up to date] testcommit1737 -> origin/testcommit1737
823 = [up to date] testcommit1738 -> origin/testcommit1738
824 = [up to date] testcommit1739 -> origin/testcommit1739
825 = [up to date] testcommit174 -> origin/testcommit174
826 = [up to date] testcommit1740 -> origin/testcommit1740
827 = [up to date] testcommit1741 -> origin/testcommit1741
828 = [up to date] testcommit1742 -> origin/testcommit1742
829 = [up to date] testcommit1743 -> origin/testcommit1743
830 = [up to date] testcommit1744 -> origin/testcommit1744
831 = [up to date] testcommit1745 -> origin/testcommit1745
832 = [up to date] testcommit1746 -> origin/testcommit1746
833 = [up to date] testcommit1747 -> origin/testcommit1747
834 = [up to date] testcommit1748 -> origin/testcommit1748
835 = [up to date] testcommit1749 -> origin/testcommit1749
836 = [up to date] testcommit175 -> origin/testcommit175
837 = [up to date] testcommit1750 -> origin/testcommit1750
838 = [up to date] testcommit1751 -> origin/testcommit1751
839 = [up to date] testcommit1752 -> origin/testcommit1752
840 = [up to date] testcommit1753 -> origin/testcommit1753
841 = [up to date] testcommit1754 -> origin/testcommit1754
842 = [up to date] testcommit1755 -> origin/testcommit1755
843 = [up to date] testcommit1756 -> origin/testcommit1756
844 = [up to date] testcommit1757 -> origin/testcommit1757
845 = [up to date] testcommit1758 -> origin/testcommit1758
846 = [up to date] testcommit1759 -> origin/testcommit1759
847 = [up to date] testcommit176 -> origin/testcommit176
848 = [up to date] testcommit1760 -> origin/testcommit1760
849 = [up to date] testcommit1761 -> origin/testcommit1761
850 = [up to date] testcommit1762 -> origin/testcommit1762
851 = [up to date] testcommit1763 -> origin/testcommit1763
852 = [up to date] testcommit1764 -> origin/testcommit1764
853 = [up to date] testcommit1765 -> origin/testcommit1765
854 = [up to date] testcommit1766 -> origin/testcommit1766
855 = [up to date] testcommit1767 -> origin/testcommit1767
856 = [up to date] testcommit1768 -> origin/testcommit1768
857 = [up to date] testcommit1769 -> origin/testcommit1769
858 = [up to date] testcommit177 -> origin/testcommit177
859 = [up to date] testcommit1770 -> origin/testcommit1770
860 = [up to date] testcommit1771 -> origin/testcommit1771
861 = [up to date] testcommit1772 -> origin/testcommit1772
862 = [up to date] testcommit1773 -> origin/testcommit1773
863 = [up to date] testcommit1774 -> origin/testcommit1774
864 = [up to date] testcommit1775 -> origin/testcommit1775
865 = [up to date] testcommit1776 -> origin/testcommit1776
866 = [up to date] testcommit1777 -> origin/testcommit1777
867 = [up to date] testcommit1778 -> origin/testcommit1778
868 = [up to date] testcommit1779 -> origin/testcommit1779
869 = [up to date] testcommit178 -> origin/testcommit178
870 = [up to date] testcommit1780 -> origin/testcommit1780
871 = [up to date] testcommit1781 -> origin/testcommit1781
872 = [up to date] testcommit1782 -> origin/testcommit1782
873 = [up to date] testcommit1783 -> origin/testcommit1783
874 = [up to date] testcommit1784 -> origin/testcommit1784
875 = [up to date] testcommit1785 -> origin/testcommit1785
876 = [up to date] testcommit1786 -> origin/testcommit1786
877 = [up to date] testcommit1787 -> origin/testcommit1787
878 = [up to date] testcommit1788 -> origin/testcommit1788
879 = [up to date] testcommit1789 -> origin/testcommit1789
880 = [up to date] testcommit179 -> origin/testcommit179
881 = [up to date] testcommit1790 -> origin/testcommit1790
882 = [up to date] testcommit1791 -> origin/testcommit1791
883 = [up to date] testcommit1792 -> origin/testcommit1792
884 = [up to date] testcommit1793 -> origin/testcommit1793
885 = [up to date] testcommit1794 -> origin/testcommit1794
886 = [up to date] testcommit1795 -> origin/testcommit1795
887 = [up to date] testcommit1796 -> origin/testcommit1796
888 = [up to date] testcommit1797 -> origin/testcommit1797
889 = [up to date] testcommit1798 -> origin/testcommit1798
890 = [up to date] testcommit1799 -> origin/testcommit1799
891 = [up to date] testcommit18 -> origin/testcommit18
892 = [up to date] testcommit180 -> origin/testcommit180
893 = [up to date] testcommit1800 -> origin/testcommit1800
894 = [up to date] testcommit1801 -> origin/testcommit1801
895 = [up to date] testcommit1802 -> origin/testcommit1802
896 = [up to date] testcommit1803 -> origin/testcommit1803
897 = [up to date] testcommit1804 -> origin/testcommit1804
898 = [up to date] testcommit1805 -> origin/testcommit1805
899 = [up to date] testcommit1806 -> origin/testcommit1806
900 = [up to date] testcommit1807 -> origin/testcommit1807
901 = [up to date] testcommit1808 -> origin/testcommit1808
902 = [up to date] testcommit1809 -> origin/testcommit1809
903 = [up to date] testcommit181 -> origin/testcommit181
904 = [up to date] testcommit1810 -> origin/testcommit1810
905 = [up to date] testcommit1811 -> origin/testcommit1811
906 = [up to date] testcommit1812 -> origin/testcommit1812
907 = [up to date] testcommit1813 -> origin/testcommit1813
908 = [up to date] testcommit1814 -> origin/testcommit1814
909 = [up to date] testcommit1815 -> origin/testcommit1815
910 = [up to date] testcommit1816 -> origin/testcommit1816
911 = [up to date] testcommit1817 -> origin/testcommit1817
912 = [up to date] testcommit1818 -> origin/testcommit1818
913 = [up to date] testcommit1819 -> origin/testcommit1819
914 = [up to date] testcommit182 -> origin/testcommit182
915 = [up to date] testcommit1820 -> origin/testcommit1820
916 = [up to date] testcommit1821 -> origin/testcommit1821
917 = [up to date] testcommit1822 -> origin/testcommit1822
918 = [up to date] testcommit1823 -> origin/testcommit1823
919 = [up to date] testcommit1824 -> origin/testcommit1824
920 = [up to date] testcommit1825 -> origin/testcommit1825
921 = [up to date] testcommit1826 -> origin/testcommit1826
922 = [up to date] testcommit1827 -> origin/testcommit1827
923 = [up to date] testcommit1828 -> origin/testcommit1828
924 = [up to date] testcommit1829 -> origin/testcommit1829
925 = [up to date] testcommit183 -> origin/testcommit183
926 = [up to date] testcommit1830 -> origin/testcommit1830
927 = [up to date] testcommit1831 -> origin/testcommit1831
928 = [up to date] testcommit1832 -> origin/testcommit1832
929 = [up to date] testcommit1833 -> origin/testcommit1833
930 = [up to date] testcommit1834 -> origin/testcommit1834
931 = [up to date] testcommit1835 -> origin/testcommit1835
932 = [up to date] testcommit1836 -> origin/testcommit1836
933 = [up to date] testcommit1837 -> origin/testcommit1837
934 = [up to date] testcommit1838 -> origin/testcommit1838
935 = [up to date] testcommit1839 -> origin/testcommit1839
936 = [up to date] testcommit184 -> origin/testcommit184
937 = [up to date] testcommit1840 -> origin/testcommit1840
938 = [up to date] testcommit1841 -> origin/testcommit1841
939 = [up to date] testcommit1842 -> origin/testcommit1842
940 = [up to date] testcommit1843 -> origin/testcommit1843
941 = [up to date] testcommit1844 -> origin/testcommit1844
942 = [up to date] testcommit1845 -> origin/testcommit1845
943 = [up to date] testcommit1846 -> origin/testcommit1846
944 = [up to date] testcommit1847 -> origin/testcommit1847
945 = [up to date] testcommit1848 -> origin/testcommit1848
946 = [up to date] testcommit1849 -> origin/testcommit1849
947 = [up to date] testcommit185 -> origin/testcommit185
948 = [up to date] testcommit1850 -> origin/testcommit1850
949 = [up to date] testcommit1851 -> origin/testcommit1851
950 = [up to date] testcommit1852 -> origin/testcommit1852
951 = [up to date] testcommit1853 -> origin/testcommit1853
952 = [up to date] testcommit1854 -> origin/testcommit1854
953 = [up to date] testcommit1855 -> origin/testcommit1855
954 = [up to date] testcommit1856 -> origin/testcommit1856
955 = [up to date] testcommit1857 -> origin/testcommit1857
956 = [up to date] testcommit1858 -> origin/testcommit1858
957 = [up to date] testcommit1859 -> origin/testcommit1859
958 = [up to date] testcommit186 -> origin/testcommit186
959 = [up to date] testcommit1860 -> origin/testcommit1860
960 = [up to date] testcommit1861 -> origin/testcommit1861
961 = [up to date] testcommit1862 -> origin/testcommit1862
962 = [up to date] testcommit1863 -> origin/testcommit1863
963 = [up to date] testcommit1864 -> origin/testcommit1864
964 = [up to date] testcommit1865 -> origin/testcommit1865
965 = [up to date] testcommit1866 -> origin/testcommit1866
966 = [up to date] testcommit1867 -> origin/testcommit1867
967 = [up to date] testcommit1868 -> origin/testcommit1868
968 = [up to date] testcommit1869 -> origin/testcommit1869
969 = [up to date] testcommit187 -> origin/testcommit187
970 = [up to date] testcommit1870 -> origin/testcommit1870
971 = [up to date] testcommit1871 -> origin/testcommit1871
972 = [up to date] testcommit1872 -> origin/testcommit1872
973 = [up to date] testcommit1873 -> origin/testcommit1873
974 = [up to date] testcommit1874 -> origin/testcommit1874
975 = [up to date] testcommit1875 -> origin/testcommit1875
976 = [up to date] testcommit1876 -> origin/testcommit1876
977 = [up to date] testcommit1877 -> origin/testcommit1877
978 = [up to date] testcommit1878 -> origin/testcommit1878
979 = [up to date] testcommit1879 -> origin/testcommit1879
980 = [up to date] testcommit188 -> origin/testcommit188
981 = [up to date] testcommit1880 -> origin/testcommit1880
982 = [up to date] testcommit1881 -> origin/testcommit1881
983 = [up to date] testcommit1882 -> origin/testcommit1882
984 = [up to date] testcommit1883 -> origin/testcommit1883
985 = [up to date] testcommit1884 -> origin/testcommit1884
986 = [up to date] testcommit1885 -> origin/testcommit1885
987 = [up to date] testcommit1886 -> origin/testcommit1886
988 = [up to date] testcommit1887 -> origin/testcommit1887
989 = [up to date] testcommit1888 -> origin/testcommit1888
990 = [up to date] testcommit1889 -> origin/testcommit1889
991 = [up to date] testcommit189 -> origin/testcommit189
992 = [up to date] testcommit1890 -> origin/testcommit1890
993 = [up to date] testcommit1891 -> origin/testcommit1891
994 = [up to date] testcommit1892 -> origin/testcommit1892
995 = [up to date] testcommit1893 -> origin/testcommit1893
996 = [up to date] testcommit1894 -> origin/testcommit1894
997 = [up to date] testcommit1895 -> origin/testcommit1895
998 = [up to date] testcommit1896 -> origin/testcommit1896
999 = [up to date] testcommit1897 -> origin/testcommit1897
1000 = [up to date] testcommit1898 -> origin/testcommit1898
1001 = [up to date] testcommit1899 -> origin/testcommit1899
1002 = [up to date] testcommit19 -> origin/testcommit19
1003 = [up to date] testcommit190 -> origin/testcommit190
1004 = [up to date] testcommit1900 -> origin/testcommit1900
1005 = [up to date] testcommit1901 -> origin/testcommit1901
1006 = [up to date] testcommit1902 -> origin/testcommit1902
1007 = [up to date] testcommit1903 -> origin/testcommit1903
1008 = [up to date] testcommit1904 -> origin/testcommit1904
1009 = [up to date] testcommit1905 -> origin/testcommit1905
1010 = [up to date] testcommit1906 -> origin/testcommit1906
1011 = [up to date] testcommit1907 -> origin/testcommit1907
1012 = [up to date] testcommit1908 -> origin/testcommit1908
1013 = [up to date] testcommit1909 -> origin/testcommit1909
1014 = [up to date] testcommit191 -> origin/testcommit191
1015 = [up to date] testcommit1910 -> origin/testcommit1910
1016 = [up to date] testcommit1911 -> origin/testcommit1911
1017 = [up to date] testcommit1912 -> origin/testcommit1912
1018 = [up to date] testcommit1913 -> origin/testcommit1913
1019 = [up to date] testcommit1914 -> origin/testcommit1914
1020 = [up to date] testcommit1915 -> origin/testcommit1915
1021 = [up to date] testcommit1916 -> origin/testcommit1916
1022 = [up to date] testcommit1917 -> origin/testcommit1917
1023 = [up to date] testcommit1918 -> origin/testcommit1918
1024 = [up to date] testcommit1919 -> origin/testcommit1919
1025 = [up to date] testcommit192 -> origin/testcommit192
1026 = [up to date] testcommit1920 -> origin/testcommit1920
1027 = [up to date] testcommit1921 -> origin/testcommit1921
1028 = [up to date] testcommit1922 -> origin/testcommit1922
1029 = [up to date] testcommit1923 -> origin/testcommit1923
1030 = [up to date] testcommit1924 -> origin/testcommit1924
1031 = [up to date] testcommit1925 -> origin/testcommit1925
1032 = [up to date] testcommit1926 -> origin/testcommit1926
1033 = [up to date] testcommit1927 -> origin/testcommit1927
1034 = [up to date] testcommit1928 -> origin/testcommit1928
1035 = [up to date] testcommit1929 -> origin/testcommit1929
1036 = [up to date] testcommit193 -> origin/testcommit193
1037 = [up to date] testcommit1930 -> origin/testcommit1930
1038 = [up to date] testcommit1931 -> origin/testcommit1931
1039 = [up to date] testcommit1932 -> origin/testcommit1932
1040 = [up to date] testcommit1933 -> origin/testcommit1933
1041 = [up to date] testcommit1934 -> origin/testcommit1934
1042 = [up to date] testcommit1935 -> origin/testcommit1935
1043 = [up to date] testcommit1936 -> origin/testcommit1936
1044 = [up to date] testcommit1937 -> origin/testcommit1937
1045 = [up to date] testcommit1938 -> origin/testcommit1938
1046 = [up to date] testcommit1939 -> origin/testcommit1939
1047 = [up to date] testcommit194 -> origin/testcommit194
1048 = [up to date] testcommit1940 -> origin/testcommit1940
1049 = [up to date] testcommit1941 -> origin/testcommit1941
1050 = [up to date] testcommit1942 -> origin/testcommit1942
1051 = [up to date] testcommit1943 -> origin/testcommit1943
1052 = [up to date] testcommit1944 -> origin/testcommit1944
1053 = [up to date] testcommit1945 -> origin/testcommit1945
1054 = [up to date] testcommit1946 -> origin/testcommit1946
1055 = [up to date] testcommit1947 -> origin/testcommit1947
1056 = [up to date] testcommit1948 -> origin/testcommit1948
1057 = [up to date] testcommit1949 -> origin/testcommit1949
1058 = [up to date] testcommit195 -> origin/testcommit195
1059 = [up to date] testcommit1950 -> origin/testcommit1950
1060 = [up to date] testcommit1951 -> origin/testcommit1951
1061 = [up to date] testcommit1952 -> origin/testcommit1952
1062 = [up to date] testcommit1953 -> origin/testcommit1953
1063 = [up to date] testcommit1954 -> origin/testcommit1954
1064 = [up to date] testcommit1955 -> origin/testcommit1955
1065 = [up to date] testcommit1956 -> origin/testcommit1956
1066 = [up to date] testcommit1957 -> origin/testcommit1957
1067 = [up to date] testcommit1958 -> origin/testcommit1958
1068 = [up to date] testcommit1959 -> origin/testcommit1959
1069 = [up to date] testcommit196 -> origin/testcommit196
1070 = [up to date] testcommit1960 -> origin/testcommit1960
1071 = [up to date] testcommit1961 -> origin/testcommit1961
1072 = [up to date] testcommit1962 -> origin/testcommit1962
1073 = [up to date] testcommit1963 -> origin/testcommit1963
1074 = [up to date] testcommit1964 -> origin/testcommit1964
1075 = [up to date] testcommit1965 -> origin/testcommit1965
1076 = [up to date] testcommit1966 -> origin/testcommit1966
1077 = [up to date] testcommit1967 -> origin/testcommit1967
1078 = [up to date] testcommit1968 -> origin/testcommit1968
1079 = [up to date] testcommit1969 -> origin/testcommit1969
1080 = [up to date] testcommit197 -> origin/testcommit197
1081 = [up to date] testcommit1970 -> origin/testcommit1970
1082 = [up to date] testcommit1971 -> origin/testcommit1971
1083 = [up to date] testcommit1972 -> origin/testcommit1972
1084 = [up to date] testcommit1973 -> origin/testcommit1973
1085 = [up to date] testcommit1974 -> origin/testcommit1974
1086 = [up to date] testcommit1975 -> origin/testcommit1975
1087 = [up to date] testcommit1976 -> origin/testcommit1976
1088 = [up to date] testcommit1977 -> origin/testcommit1977
1089 = [up to date] testcommit1978 -> origin/testcommit1978
1090 = [up to date] testcommit1979 -> origin/testcommit1979
1091 = [up to date] testcommit198 -> origin/testcommit198
1092 = [up to date] testcommit1980 -> origin/testcommit1980
1093 = [up to date] testcommit1981 -> origin/testcommit1981
1094 = [up to date] testcommit1982 -> origin/testcommit1982
1095 = [up to date] testcommit1983 -> origin/testcommit1983
1096 = [up to date] testcommit1984 -> origin/testcommit1984
1097 = [up to date] testcommit1985 -> origin/testcommit1985
1098 = [up to date] testcommit1986 -> origin/testcommit1986
1099 = [up to date] testcommit1987 -> origin/testcommit1987
1100 = [up to date] testcommit1988 -> origin/testcommit1988
1101 = [up to date] testcommit1989 -> origin/testcommit1989
1102 = [up to date] testcommit199 -> origin/testcommit199
1103 = [up to date] testcommit1990 -> origin/testcommit1990
1104 = [up to date] testcommit1991 -> origin/testcommit1991
1105 = [up to date] testcommit1992 -> origin/testcommit1992
1106 = [up to date] testcommit1993 -> origin/testcommit1993
1107 = [up to date] testcommit1994 -> origin/testcommit1994
1108 = [up to date] testcommit1995 -> origin/testcommit1995
1109 = [up to date] testcommit1996 -> origin/testcommit1996
1110 = [up to date] testcommit1997 -> origin/testcommit1997
1111 = [up to date] testcommit1998 -> origin/testcommit1998
1112 = [up to date] testcommit1999 -> origin/testcommit1999
1113 = [up to date] testcommit2 -> origin/testcommit2
1114 = [up to date] testcommit20 -> origin/testcommit20
1115 = [up to date] testcommit200 -> origin/testcommit200
1116 = [up to date] testcommit2000 -> origin/testcommit2000
1117 = [up to date] testcommit2001 -> origin/testcommit2001
1118 = [up to date] testcommit2002 -> origin/testcommit2002
1119 = [up to date] testcommit2003 -> origin/testcommit2003
1120 = [up to date] testcommit2004 -> origin/testcommit2004
1121 = [up to date] testcommit2005 -> origin/testcommit2005
1122 = [up to date] testcommit2006 -> origin/testcommit2006
1123 = [up to date] testcommit2007 -> origin/testcommit2007
1124 = [up to date] testcommit2008 -> origin/testcommit2008
1125 = [up to date] testcommit2009 -> origin/testcommit2009
1126 = [up to date] testcommit201 -> origin/testcommit201
1127 = [up to date] testcommit2010 -> origin/testcommit2010
1128 = [up to date] testcommit2011 -> origin/testcommit2011
1129 = [up to date] testcommit2012 -> origin/testcommit2012
1130 = [up to date] testcommit2013 -> origin/testcommit2013
1131 = [up to date] testcommit2014 -> origin/testcommit2014
1132 = [up to date] testcommit2015 -> origin/testcommit2015
1133 = [up to date] testcommit2016 -> origin/testcommit2016
1134 = [up to date] testcommit2017 -> origin/testcommit2017
1135 = [up to date] testcommit2018 -> origin/testcommit2018
1136 = [up to date] testcommit2019 -> origin/testcommit2019
1137 = [up to date] testcommit202 -> origin/testcommit202
1138 = [up to date] testcommit2020 -> origin/testcommit2020
1139 = [up to date] testcommit2021 -> origin/testcommit2021
1140 = [up to date] testcommit2022 -> origin/testcommit2022
1141 = [up to date] testcommit2023 -> origin/testcommit2023
1142 = [up to date] testcommit2024 -> origin/testcommit2024
1143 = [up to date] testcommit2025 -> origin/testcommit2025
1144 = [up to date] testcommit2026 -> origin/testcommit2026
1145 = [up to date] testcommit2027 -> origin/testcommit2027
1146 = [up to date] testcommit2028 -> origin/testcommit2028
1147 = [up to date] testcommit2029 -> origin/testcommit2029
1148 = [up to date] testcommit203 -> origin/testcommit203
1149 = [up to date] testcommit2030 -> origin/testcommit2030
1150 = [up to date] testcommit2031 -> origin/testcommit2031
1151 = [up to date] testcommit2032 -> origin/testcommit2032
1152 = [up to date] testcommit2033 -> origin/testcommit2033
1153 = [up to date] testcommit2034 -> origin/testcommit2034
1154 = [up to date] testcommit2035 -> origin/testcommit2035
1155 = [up to date] testcommit2036 -> origin/testcommit2036
1156 = [up to date] testcommit2037 -> origin/testcommit2037
1157 = [up to date] testcommit2038 -> origin/testcommit2038
1158 = [up to date] testcommit2039 -> origin/testcommit2039
1159 = [up to date] testcommit204 -> origin/testcommit204
1160 = [up to date] testcommit2040 -> origin/testcommit2040
1161 = [up to date] testcommit2041 -> origin/testcommit2041
1162 = [up to date] testcommit2042 -> origin/testcommit2042
1163 = [up to date] testcommit2043 -> origin/testcommit2043
1164 = [up to date] testcommit2044 -> origin/testcommit2044
1165 = [up to date] testcommit2045 -> origin/testcommit2045
1166 = [up to date] testcommit2046 -> origin/testcommit2046
1167 = [up to date] testcommit2047 -> origin/testcommit2047
1168 = [up to date] testcommit2048 -> origin/testcommit2048
1169 = [up to date] testcommit2049 -> origin/testcommit2049
1170 = [up to date] testcommit205 -> origin/testcommit205
1171 = [up to date] testcommit2050 -> origin/testcommit2050
1172 = [up to date] testcommit2051 -> origin/testcommit2051
1173 = [up to date] testcommit2052 -> origin/testcommit2052
1174 = [up to date] testcommit2053 -> origin/testcommit2053
1175 = [up to date] testcommit2054 -> origin/testcommit2054
1176 = [up to date] testcommit2055 -> origin/testcommit2055
1177 = [up to date] testcommit2056 -> origin/testcommit2056
1178 = [up to date] testcommit2057 -> origin/testcommit2057
1179 = [up to date] testcommit2058 -> origin/testcommit2058
1180 = [up to date] testcommit2059 -> origin/testcommit2059
1181 = [up to date] testcommit206 -> origin/testcommit206
1182 = [up to date] testcommit2060 -> origin/testcommit2060
1183 = [up to date] testcommit2061 -> origin/testcommit2061
1184 = [up to date] testcommit2062 -> origin/testcommit2062
1185 = [up to date] testcommit2063 -> origin/testcommit2063
1186 = [up to date] testcommit2064 -> origin/testcommit2064
1187 = [up to date] testcommit2065 -> origin/testcommit2065
1188 = [up to date] testcommit2066 -> origin/testcommit2066
1189 = [up to date] testcommit2067 -> origin/testcommit2067
1190 = [up to date] testcommit2068 -> origin/testcommit2068
1191 = [up to date] testcommit2069 -> origin/testcommit2069
1192 = [up to date] testcommit207 -> origin/testcommit207
1193 = [up to date] testcommit2070 -> origin/testcommit2070
1194 = [up to date] testcommit2071 -> origin/testcommit2071
1195 = [up to date] testcommit2072 -> origin/testcommit2072
1196 = [up to date] testcommit2073 -> origin/testcommit2073
1197 = [up to date] testcommit2074 -> origin/testcommit2074
1198 = [up to date] testcommit2075 -> origin/testcommit2075
1199 = [up to date] testcommit2076 -> origin/testcommit2076
1200 = [up to date] testcommit2077 -> origin/testcommit2077
1201 = [up to date] testcommit2078 -> origin/testcommit2078
1202 = [up to date] testcommit2079 -> origin/testcommit2079
1203 = [up to date] testcommit208 -> origin/testcommit208
1204 = [up to date] testcommit2080 -> origin/testcommit2080
1205 = [up to date] testcommit2081 -> origin/testcommit2081
1206 = [up to date] testcommit2082 -> origin/testcommit2082
1207 = [up to date] testcommit2083 -> origin/testcommit2083
1208 = [up to date] testcommit2084 -> origin/testcommit2084
1209 = [up to date] testcommit2085 -> origin/testcommit2085
1210 = [up to date] testcommit2086 -> origin/testcommit2086
1211 = [up to date] testcommit2087 -> origin/testcommit2087
1212 = [up to date] testcommit2088 -> origin/testcommit2088
1213 = [up to date] testcommit2089 -> origin/testcommit2089
1214 = [up to date] testcommit209 -> origin/testcommit209
1215 = [up to date] testcommit2090 -> origin/testcommit2090
1216 = [up to date] testcommit2091 -> origin/testcommit2091
1217 = [up to date] testcommit2092 -> origin/testcommit2092
1218 = [up to date] testcommit2093 -> origin/testcommit2093
1219 = [up to date] testcommit2094 -> origin/testcommit2094
1220 = [up to date] testcommit2095 -> origin/testcommit2095
1221 = [up to date] testcommit2096 -> origin/testcommit2096
1222 = [up to date] testcommit2097 -> origin/testcommit2097
1223 = [up to date] testcommit2098 -> origin/testcommit2098
1224 = [up to date] testcommit2099 -> origin/testcommit2099
1225 = [up to date] testcommit21 -> origin/testcommit21
1226 = [up to date] testcommit210 -> origin/testcommit210
1227 = [up to date] testcommit2100 -> origin/testcommit2100
1228 = [up to date] testcommit2101 -> origin/testcommit2101
1229 = [up to date] testcommit2102 -> origin/testcommit2102
1230 = [up to date] testcommit2103 -> origin/testcommit2103
1231 = [up to date] testcommit2104 -> origin/testcommit2104
1232 = [up to date] testcommit2105 -> origin/testcommit2105
1233 = [up to date] testcommit2106 -> origin/testcommit2106
1234 = [up to date] testcommit2107 -> origin/testcommit2107
1235 = [up to date] testcommit2108 -> origin/testcommit2108
1236 = [up to date] testcommit2109 -> origin/testcommit2109
1237 = [up to date] testcommit211 -> origin/testcommit211
1238 = [up to date] testcommit2110 -> origin/testcommit2110
1239 = [up to date] testcommit2111 -> origin/testcommit2111
1240 = [up to date] testcommit2112 -> origin/testcommit2112
1241 = [up to date] testcommit2113 -> origin/testcommit2113
1242 = [up to date] testcommit2114 -> origin/testcommit2114
1243 = [up to date] testcommit2115 -> origin/testcommit2115
1244 = [up to date] testcommit2116 -> origin/testcommit2116
1245 = [up to date] testcommit2117 -> origin/testcommit2117
1246 = [up to date] testcommit2118 -> origin/testcommit2118
1247 = [up to date] testcommit2119 -> origin/testcommit2119
1248 = [up to date] testcommit212 -> origin/testcommit212
1249 = [up to date] testcommit2120 -> origin/testcommit2120
1250 = [up to date] testcommit2121 -> origin/testcommit2121
1251 = [up to date] testcommit2122 -> origin/testcommit2122
1252 = [up to date] testcommit2123 -> origin/testcommit2123
1253 = [up to date] testcommit2124 -> origin/testcommit2124
1254 = [up to date] testcommit2125 -> origin/testcommit2125
1255 = [up to date] testcommit2126 -> origin/testcommit2126
1256 = [up to date] testcommit2127 -> origin/testcommit2127
1257 = [up to date] testcommit2128 -> origin/testcommit2128
1258 = [up to date] testcommit2129 -> origin/testcommit2129
1259 = [up to date] testcommit213 -> origin/testcommit213
1260 = [up to date] testcommit2130 -> origin/testcommit2130
1261 = [up to date] testcommit2131 -> origin/testcommit2131
1262 = [up to date] testcommit2132 -> origin/testcommit2132
1263 = [up to date] testcommit2133 -> origin/testcommit2133
1264 = [up to date] testcommit2134 -> origin/testcommit2134
1265 = [up to date] testcommit2135 -> origin/testcommit2135
1266 = [up to date] testcommit2136 -> origin/testcommit2136
1267 = [up to date] testcommit2137 -> origin/testcommit2137
1268 = [up to date] testcommit2138 -> origin/testcommit2138
1269 = [up to date] testcommit2139 -> origin/testcommit2139
1270 = [up to date] testcommit214 -> origin/testcommit214
1271 = [up to date] testcommit2140 -> origin/testcommit2140
1272 = [up to date] testcommit2141 -> origin/testcommit2141
1273 = [up to date] testcommit2142 -> origin/testcommit2142
1274 = [up to date] testcommit2143 -> origin/testcommit2143
1275 = [up to date] testcommit2144 -> origin/testcommit2144
1276 = [up to date] testcommit2145 -> origin/testcommit2145
1277 = [up to date] testcommit2146 -> origin/testcommit2146
1278 = [up to date] testcommit2147 -> origin/testcommit2147
1279 = [up to date] testcommit2148 -> origin/testcommit2148
1280 = [up to date] testcommit2149 -> origin/testcommit2149
1281 = [up to date] testcommit215 -> origin/testcommit215
1282 = [up to date] testcommit2150 -> origin/testcommit2150
1283 = [up to date] testcommit2151 -> origin/testcommit2151
1284 = [up to date] testcommit2152 -> origin/testcommit2152
1285 = [up to date] testcommit2153 -> origin/testcommit2153
1286 = [up to date] testcommit2154 -> origin/testcommit2154
1287 = [up to date] testcommit2155 -> origin/testcommit2155
1288 = [up to date] testcommit2156 -> origin/testcommit2156
1289 = [up to date] testcommit2157 -> origin/testcommit2157
1290 = [up to date] testcommit2158 -> origin/testcommit2158
1291 = [up to date] testcommit2159 -> origin/testcommit2159
1292 = [up to date] testcommit216 -> origin/testcommit216
1293 = [up to date] testcommit2160 -> origin/testcommit2160
1294 = [up to date] testcommit2161 -> origin/testcommit2161
1295 = [up to date] testcommit2162 -> origin/testcommit2162
1296 = [up to date] testcommit2163 -> origin/testcommit2163
1297 = [up to date] testcommit2164 -> origin/testcommit2164
1298 = [up to date] testcommit2165 -> origin/testcommit2165
1299 = [up to date] testcommit2166 -> origin/testcommit2166
1300 = [up to date] testcommit2167 -> origin/testcommit2167
1301 = [up to date] testcommit2168 -> origin/testcommit2168
1302 = [up to date] testcommit2169 -> origin/testcommit2169
1303 = [up to date] testcommit217 -> origin/testcommit217
1304 = [up to date] testcommit2170 -> origin/testcommit2170
1305 = [up to date] testcommit2171 -> origin/testcommit2171
1306 = [up to date] testcommit2172 -> origin/testcommit2172
1307 = [up to date] testcommit2173 -> origin/testcommit2173
1308 = [up to date] testcommit2174 -> origin/testcommit2174
1309 = [up to date] testcommit2175 -> origin/testcommit2175
1310 = [up to date] testcommit2176 -> origin/testcommit2176
1311 = [up to date] testcommit2177 -> origin/testcommit2177
1312 = [up to date] testcommit2178 -> origin/testcommit2178
1313 = [up to date] testcommit2179 -> origin/testcommit2179
1314 = [up to date] testcommit218 -> origin/testcommit218
1315 = [up to date] testcommit2180 -> origin/testcommit2180
1316 = [up to date] testcommit2181 -> origin/testcommit2181
1317 = [up to date] testcommit2182 -> origin/testcommit2182
1318 = [up to date] testcommit2183 -> origin/testcommit2183
1319 = [up to date] testcommit2184 -> origin/testcommit2184
1320 = [up to date] testcommit2185 -> origin/testcommit2185
1321 = [up to date] testcommit2186 -> origin/testcommit2186
1322 = [up to date] testcommit2187 -> origin/testcommit2187
1323 = [up to date] testcommit2188 -> origin/testcommit2188
1324 = [up to date] testcommit2189 -> origin/testcommit2189
1325 = [up to date] testcommit219 -> origin/testcommit219
1326 = [up to date] testcommit2190 -> origin/testcommit2190
1327 = [up to date] testcommit2191 -> origin/testcommit2191
1328 = [up to date] testcommit2192 -> origin/testcommit2192
1329 = [up to date] testcommit2193 -> origin/testcommit2193
1330 = [up to date] testcommit2194 -> origin/testcommit2194
1331 = [up to date] testcommit2195 -> origin/testcommit2195
1332 = [up to date] testcommit2196 -> origin/testcommit2196
1333 = [up to date] testcommit2197 -> origin/testcommit2197
1334 = [up to date] testcommit2198 -> origin/testcommit2198
1335 = [up to date] testcommit2199 -> origin/testcommit2199
1336 = [up to date] testcommit22 -> origin/testcommit22
1337 = [up to date] testcommit220 -> origin/testcommit220
1338 = [up to date] testcommit2200 -> origin/testcommit2200
1339 = [up to date] testcommit2201 -> origin/testcommit2201
1340 = [up to date] testcommit2202 -> origin/testcommit2202
1341 = [up to date] testcommit2203 -> origin/testcommit2203
1342 = [up to date] testcommit2204 -> origin/testcommit2204
1343 = [up to date] testcommit2205 -> origin/testcommit2205
1344 = [up to date] testcommit2206 -> origin/testcommit2206
1345 = [up to date] testcommit2207 -> origin/testcommit2207
1346 = [up to date] testcommit2208 -> origin/testcommit2208
1347 = [up to date] testcommit2209 -> origin/testcommit2209
1348 = [up to date] testcommit221 -> origin/testcommit221
1349 = [up to date] testcommit2210 -> origin/testcommit2210
1350 = [up to date] testcommit2211 -> origin/testcommit2211
1351 = [up to date] testcommit2212 -> origin/testcommit2212
1352 = [up to date] testcommit2213 -> origin/testcommit2213
1353 = [up to date] testcommit2214 -> origin/testcommit2214
1354 = [up to date] testcommit2215 -> origin/testcommit2215
1355 = [up to date] testcommit2216 -> origin/testcommit2216
1356 = [up to date] testcommit2217 -> origin/testcommit2217
1357 = [up to date] testcommit2218 -> origin/testcommit2218
1358 = [up to date] testcommit2219 -> origin/testcommit2219
1359 = [up to date] testcommit222 -> origin/testcommit222
1360 = [up to date] testcommit2220 -> origin/testcommit2220
1361 = [up to date] testcommit2221 -> origin/testcommit2221
1362 = [up to date] testcommit2222 -> origin/testcommit2222
1363 = [up to date] testcommit2223 -> origin/testcommit2223
1364 = [up to date] testcommit2224 -> origin/testcommit2224
1365 = [up to date] testcommit2225 -> origin/testcommit2225
1366 = [up to date] testcommit2226 -> origin/testcommit2226
1367 = [up to date] testcommit2227 -> origin/testcommit2227
1368 = [up to date] testcommit2228 -> origin/testcommit2228
1369 = [up to date] testcommit2229 -> origin/testcommit2229
1370 = [up to date] testcommit223 -> origin/testcommit223
1371 = [up to date] testcommit2230 -> origin/testcommit2230
1372 = [up to date] testcommit2231 -> origin/testcommit2231
1373 = [up to date] testcommit2232 -> origin/testcommit2232
1374 = [up to date] testcommit2233 -> origin/testcommit2233
1375 = [up to date] testcommit2234 -> origin/testcommit2234
1376 = [up to date] testcommit2235 -> origin/testcommit2235
1377 = [up to date] testcommit2236 -> origin/testcommit2236
1378 = [up to date] testcommit2237 -> origin/testcommit2237
1379 = [up to date] testcommit2238 -> origin/testcommit2238
1380 = [up to date] testcommit2239 -> origin/testcommit2239
1381 = [up to date] testcommit224 -> origin/testcommit224
1382 = [up to date] testcommit2240 -> origin/testcommit2240
1383 = [up to date] testcommit2241 -> origin/testcommit2241
1384 = [up to date] testcommit2242 -> origin/testcommit2242
1385 = [up to date] testcommit2243 -> origin/testcommit2243
1386 = [up to date] testcommit2244 -> origin/testcommit2244
1387 = [up to date] testcommit2245 -> origin/testcommit2245
1388 = [up to date] testcommit2246 -> origin/testcommit2246
1389 = [up to date] testcommit2247 -> origin/testcommit2247
1390 = [up to date] testcommit2248 -> origin/testcommit2248
1391 = [up to date] testcommit2249 -> origin/testcommit2249
1392 = [up to date] testcommit225 -> origin/testcommit225
1393 = [up to date] testcommit2250 -> origin/testcommit2250
1394 = [up to date] testcommit2251 -> origin/testcommit2251
1395 = [up to date] testcommit2252 -> origin/testcommit2252
1396 = [up to date] testcommit2253 -> origin/testcommit2253
1397 = [up to date] testcommit2254 -> origin/testcommit2254
1398 = [up to date] testcommit2255 -> origin/testcommit2255
1399 = [up to date] testcommit2256 -> origin/testcommit2256
1400 = [up to date] testcommit2257 -> origin/testcommit2257
1401 = [up to date] testcommit2258 -> origin/testcommit2258
1402 = [up to date] testcommit2259 -> origin/testcommit2259
1403 = [up to date] testcommit226 -> origin/testcommit226
1404 = [up to date] testcommit2260 -> origin/testcommit2260
1405 = [up to date] testcommit2261 -> origin/testcommit2261
1406 = [up to date] testcommit2262 -> origin/testcommit2262
1407 = [up to date] testcommit2263 -> origin/testcommit2263
1408 = [up to date] testcommit2264 -> origin/testcommit2264
1409 = [up to date] testcommit2265 -> origin/testcommit2265
1410 = [up to date] testcommit2266 -> origin/testcommit2266
1411 = [up to date] testcommit2267 -> origin/testcommit2267
1412 = [up to date] testcommit2268 -> origin/testcommit2268
1413 = [up to date] testcommit2269 -> origin/testcommit2269
1414 = [up to date] testcommit227 -> origin/testcommit227
1415 = [up to date] testcommit2270 -> origin/testcommit2270
1416 = [up to date] testcommit2271 -> origin/testcommit2271
1417 = [up to date] testcommit2272 -> origin/testcommit2272
1418 = [up to date] testcommit2273 -> origin/testcommit2273
1419 = [up to date] testcommit2274 -> origin/testcommit2274
1420 = [up to date] testcommit2275 -> origin/testcommit2275
1421 = [up to date] testcommit2276 -> origin/testcommit2276
1422 = [up to date] testcommit2277 -> origin/testcommit2277
1423 = [up to date] testcommit2278 -> origin/testcommit2278
1424 = [up to date] testcommit2279 -> origin/testcommit2279
1425 = [up to date] testcommit228 -> origin/testcommit228
1426 = [up to date] testcommit2280 -> origin/testcommit2280
1427 = [up to date] testcommit2281 -> origin/testcommit2281
1428 = [up to date] testcommit2282 -> origin/testcommit2282
1429 = [up to date] testcommit2283 -> origin/testcommit2283
1430 = [up to date] testcommit2284 -> origin/testcommit2284
1431 = [up to date] testcommit2285 -> origin/testcommit2285
1432 = [up to date] testcommit2286 -> origin/testcommit2286
1433 = [up to date] testcommit2287 -> origin/testcommit2287
1434 = [up to date] testcommit2288 -> origin/testcommit2288
1435 = [up to date] testcommit2289 -> origin/testcommit2289
1436 = [up to date] testcommit229 -> origin/testcommit229
1437 = [up to date] testcommit2290 -> origin/testcommit2290
1438 = [up to date] testcommit2291 -> origin/testcommit2291
1439 = [up to date] testcommit2292 -> origin/testcommit2292
1440 = [up to date] testcommit2293 -> origin/testcommit2293
1441 = [up to date] testcommit2294 -> origin/testcommit2294
1442 = [up to date] testcommit2295 -> origin/testcommit2295
1443 = [up to date] testcommit2296 -> origin/testcommit2296
1444 = [up to date] testcommit2297 -> origin/testcommit2297
1445 = [up to date] testcommit2298 -> origin/testcommit2298
1446 = [up to date] testcommit2299 -> origin/testcommit2299
1447 = [up to date] testcommit23 -> origin/testcommit23
1448 = [up to date] testcommit230 -> origin/testcommit230
1449 = [up to date] testcommit2300 -> origin/testcommit2300
1450 = [up to date] testcommit2301 -> origin/testcommit2301
1451 = [up to date] testcommit2302 -> origin/testcommit2302
1452 = [up to date] testcommit2303 -> origin/testcommit2303
1453 = [up to date] testcommit2304 -> origin/testcommit2304
1454 = [up to date] testcommit2305 -> origin/testcommit2305
1455 = [up to date] testcommit2306 -> origin/testcommit2306
1456 = [up to date] testcommit2307 -> origin/testcommit2307
1457 = [up to date] testcommit2308 -> origin/testcommit2308
1458 = [up to date] testcommit2309 -> origin/testcommit2309
1459 = [up to date] testcommit231 -> origin/testcommit231
1460 = [up to date] testcommit2310 -> origin/testcommit2310
1461 = [up to date] testcommit2311 -> origin/testcommit2311
1462 = [up to date] testcommit2312 -> origin/testcommit2312
1463 = [up to date] testcommit2313 -> origin/testcommit2313
1464 = [up to date] testcommit2314 -> origin/testcommit2314
1465 = [up to date] testcommit2315 -> origin/testcommit2315
1466 = [up to date] testcommit2316 -> origin/testcommit2316
1467 = [up to date] testcommit2317 -> origin/testcommit2317
1468 = [up to date] testcommit2318 -> origin/testcommit2318
1469 = [up to date] testcommit2319 -> origin/testcommit2319
1470 = [up to date] testcommit232 -> origin/testcommit232
1471 = [up to date] testcommit2320 -> origin/testcommit2320
1472 = [up to date] testcommit2321 -> origin/testcommit2321
1473 = [up to date] testcommit2322 -> origin/testcommit2322
1474 = [up to date] testcommit2323 -> origin/testcommit2323
1475 = [up to date] testcommit2324 -> origin/testcommit2324
1476 = [up to date] testcommit2325 -> origin/testcommit2325
1477 = [up to date] testcommit2326 -> origin/testcommit2326
1478 = [up to date] testcommit2327 -> origin/testcommit2327
1479 = [up to date] testcommit2328 -> origin/testcommit2328
1480 = [up to date] testcommit2329 -> origin/testcommit2329
1481 = [up to date] testcommit233 -> origin/testcommit233
1482 = [up to date] testcommit2330 -> origin/testcommit2330
1483 = [up to date] testcommit2331 -> origin/testcommit2331
1484 = [up to date] testcommit2332 -> origin/testcommit2332
1485 = [up to date] testcommit2333 -> origin/testcommit2333
1486 = [up to date] testcommit2334 -> origin/testcommit2334
1487 = [up to date] testcommit2335 -> origin/testcommit2335
1488 = [up to date] testcommit2336 -> origin/testcommit2336
1489 = [up to date] testcommit2337 -> origin/testcommit2337
1490 = [up to date] testcommit2338 -> origin/testcommit2338
1491 = [up to date] testcommit2339 -> origin/testcommit2339
1492 = [up to date] testcommit234 -> origin/testcommit234
1493 = [up to date] testcommit2340 -> origin/testcommit2340
1494 = [up to date] testcommit2341 -> origin/testcommit2341
1495 = [up to date] testcommit2342 -> origin/testcommit2342
1496 = [up to date] testcommit2343 -> origin/testcommit2343
1497 = [up to date] testcommit2344 -> origin/testcommit2344
1498 = [up to date] testcommit2345 -> origin/testcommit2345
1499 = [up to date] testcommit2346 -> origin/testcommit2346
1500 = [up to date] testcommit2347 -> origin/testcommit2347
1501 = [up to date] testcommit2348 -> origin/testcommit2348
1502 = [up to date] testcommit2349 -> origin/testcommit2349
1503 = [up to date] testcommit235 -> origin/testcommit235
1504 = [up to date] testcommit2350 -> origin/testcommit2350
1505 = [up to date] testcommit2351 -> origin/testcommit2351
1506 = [up to date] testcommit2352 -> origin/testcommit2352
1507 = [up to date] testcommit2353 -> origin/testcommit2353
1508 = [up to date] testcommit2354 -> origin/testcommit2354
1509 = [up to date] testcommit2355 -> origin/testcommit2355
1510 = [up to date] testcommit2356 -> origin/testcommit2356
1511 = [up to date] testcommit2357 -> origin/testcommit2357
1512 = [up to date] testcommit2358 -> origin/testcommit2358
1513 = [up to date] testcommit2359 -> origin/testcommit2359
1514 = [up to date] testcommit236 -> origin/testcommit236
1515 = [up to date] testcommit2360 -> origin/testcommit2360
1516 = [up to date] testcommit2361 -> origin/testcommit2361
1517 = [up to date] testcommit2362 -> origin/testcommit2362
1518 = [up to date] testcommit2363 -> origin/testcommit2363
1519 = [up to date] testcommit2364 -> origin/testcommit2364
1520 = [up to date] testcommit2365 -> origin/testcommit2365
1521 = [up to date] testcommit2366 -> origin/testcommit2366
1522 = [up to date] testcommit2367 -> origin/testcommit2367
1523 = [up to date] testcommit2368 -> origin/testcommit2368
1524 = [up to date] testcommit2369 -> origin/testcommit2369
1525 = [up to date] testcommit237 -> origin/testcommit237
1526 = [up to date] testcommit2370 -> origin/testcommit2370
1527 = [up to date] testcommit2371 -> origin/testcommit2371
1528 = [up to date] testcommit2372 -> origin/testcommit2372
1529 = [up to date] testcommit2373 -> origin/testcommit2373
1530 = [up to date] testcommit2374 -> origin/testcommit2374
1531 = [up to date] testcommit2375 -> origin/testcommit2375
1532 = [up to date] testcommit2376 -> origin/testcommit2376
1533 = [up to date] testcommit2377 -> origin/testcommit2377
1534 = [up to date] testcommit2378 -> origin/testcommit2378
1535 = [up to date] testcommit2379 -> origin/testcommit2379
1536 = [up to date] testcommit238 -> origin/testcommit238
1537 = [up to date] testcommit2380 -> origin/testcommit2380
1538 = [up to date] testcommit2381 -> origin/testcommit2381
1539 = [up to date] testcommit2382 -> origin/testcommit2382
1540 = [up to date] testcommit2383 -> origin/testcommit2383
1541 = [up to date] testcommit2384 -> origin/testcommit2384
1542 = [up to date] testcommit2385 -> origin/testcommit2385
1543 = [up to date] testcommit2386 -> origin/testcommit2386
1544 = [up to date] testcommit2387 -> origin/testcommit2387
1545 = [up to date] testcommit2388 -> origin/testcommit2388
1546 = [up to date] testcommit2389 -> origin/testcommit2389
1547 = [up to date] testcommit239 -> origin/testcommit239
1548 = [up to date] testcommit2390 -> origin/testcommit2390
1549 = [up to date] testcommit2391 -> origin/testcommit2391
1550 = [up to date] testcommit2392 -> origin/testcommit2392
1551 = [up to date] testcommit2393 -> origin/testcommit2393
1552 = [up to date] testcommit2394 -> origin/testcommit2394
1553 = [up to date] testcommit2395 -> origin/testcommit2395
1554 = [up to date] testcommit2396 -> origin/testcommit2396
1555 = [up to date] testcommit2397 -> origin/testcommit2397
1556 = [up to date] testcommit2398 -> origin/testcommit2398
1557 = [up to date] testcommit2399 -> origin/testcommit2399
1558 = [up to date] testcommit24 -> origin/testcommit24
1559 = [up to date] testcommit240 -> origin/testcommit240
1560 = [up to date] testcommit2400 -> origin/testcommit2400
1561 = [up to date] testcommit2401 -> origin/testcommit2401
1562 = [up to date] testcommit2402 -> origin/testcommit2402
1563 = [up to date] testcommit2403 -> origin/testcommit2403
1564 = [up to date] testcommit2404 -> origin/testcommit2404
1565 = [up to date] testcommit2405 -> origin/testcommit2405
1566 = [up to date] testcommit2406 -> origin/testcommit2406
1567 = [up to date] testcommit2407 -> origin/testcommit2407
1568 = [up to date] testcommit2408 -> origin/testcommit2408
1569 = [up to date] testcommit2409 -> origin/testcommit2409
1570 = [up to date] testcommit241 -> origin/testcommit241
1571 = [up to date] testcommit2410 -> origin/testcommit2410
1572 = [up to date] testcommit2411 -> origin/testcommit2411
1573 = [up to date] testcommit2412 -> origin/testcommit2412
1574 = [up to date] testcommit2413 -> origin/testcommit2413
1575 = [up to date] testcommit2414 -> origin/testcommit2414
1576 = [up to date] testcommit2415 -> origin/testcommit2415
1577 = [up to date] testcommit2416 -> origin/testcommit2416
1578 = [up to date] testcommit2417 -> origin/testcommit2417
1579 = [up to date] testcommit2418 -> origin/testcommit2418
1580 = [up to date] testcommit2419 -> origin/testcommit2419
1581 = [up to date] testcommit242 -> origin/testcommit242
1582 = [up to date] testcommit2420 -> origin/testcommit2420
1583 = [up to date] testcommit2421 -> origin/testcommit2421
1584 = [up to date] testcommit2422 -> origin/testcommit2422
1585 = [up to date] testcommit2423 -> origin/testcommit2423
1586 = [up to date] testcommit2424 -> origin/testcommit2424
1587 = [up to date] testcommit2425 -> origin/testcommit2425
1588 = [up to date] testcommit2426 -> origin/testcommit2426
1589 = [up to date] testcommit2427 -> origin/testcommit2427
1590 = [up to date] testcommit2428 -> origin/testcommit2428
1591 = [up to date] testcommit2429 -> origin/testcommit2429
1592 = [up to date] testcommit243 -> origin/testcommit243
1593 = [up to date] testcommit2430 -> origin/testcommit2430
1594 = [up to date] testcommit2431 -> origin/testcommit2431
1595 = [up to date] testcommit2432 -> origin/testcommit2432
1596 = [up to date] testcommit2433 -> origin/testcommit2433
1597 = [up to date] testcommit2434 -> origin/testcommit2434
1598 = [up to date] testcommit2435 -> origin/testcommit2435
1599 = [up to date] testcommit2436 -> origin/testcommit2436
1600 = [up to date] testcommit2437 -> origin/testcommit2437
1601 = [up to date] testcommit2438 -> origin/testcommit2438
1602 = [up to date] testcommit2439 -> origin/testcommit2439
1603 = [up to date] testcommit244 -> origin/testcommit244
1604 = [up to date] testcommit2440 -> origin/testcommit2440
1605 = [up to date] testcommit2441 -> origin/testcommit2441
1606 = [up to date] testcommit2442 -> origin/testcommit2442
1607 = [up to date] testcommit2443 -> origin/testcommit2443
1608 = [up to date] testcommit2444 -> origin/testcommit2444
1609 = [up to date] testcommit2445 -> origin/testcommit2445
1610 = [up to date] testcommit2446 -> origin/testcommit2446
1611 = [up to date] testcommit2447 -> origin/testcommit2447
1612 = [up to date] testcommit2448 -> origin/testcommit2448
1613 = [up to date] testcommit2449 -> origin/testcommit2449
1614 = [up to date] testcommit245 -> origin/testcommit245
1615 = [up to date] testcommit2450 -> origin/testcommit2450
1616 = [up to date] testcommit2451 -> origin/testcommit2451
1617 = [up to date] testcommit2452 -> origin/testcommit2452
1618 = [up to date] testcommit2453 -> origin/testcommit2453
1619 = [up to date] testcommit2454 -> origin/testcommit2454
1620 = [up to date] testcommit2455 -> origin/testcommit2455
1621 = [up to date] testcommit2456 -> origin/testcommit2456
1622 = [up to date] testcommit2457 -> origin/testcommit2457
1623 = [up to date] testcommit2458 -> origin/testcommit2458
1624 = [up to date] testcommit2459 -> origin/testcommit2459
1625 = [up to date] testcommit246 -> origin/testcommit246
1626 = [up to date] testcommit2460 -> origin/testcommit2460
1627 = [up to date] testcommit2461 -> origin/testcommit2461
1628 = [up to date] testcommit2462 -> origin/testcommit2462
1629 = [up to date] testcommit2463 -> origin/testcommit2463
1630 = [up to date] testcommit2464 -> origin/testcommit2464
1631 = [up to date] testcommit2465 -> origin/testcommit2465
1632 = [up to date] testcommit2466 -> origin/testcommit2466
1633 = [up to date] testcommit2467 -> origin/testcommit2467
1634 = [up to date] testcommit2468 -> origin/testcommit2468
1635 = [up to date] testcommit2469 -> origin/testcommit2469
1636 = [up to date] testcommit247 -> origin/testcommit247
1637 = [up to date] testcommit2470 -> origin/testcommit2470
1638 = [up to date] testcommit2471 -> origin/testcommit2471
1639 = [up to date] testcommit2472 -> origin/testcommit2472
1640 = [up to date] testcommit2473 -> origin/testcommit2473
1641 = [up to date] testcommit2474 -> origin/testcommit2474
1642 = [up to date] testcommit2475 -> origin/testcommit2475
1643 = [up to date] testcommit2476 -> origin/testcommit2476
1644 = [up to date] testcommit2477 -> origin/testcommit2477
1645 = [up to date] testcommit2478 -> origin/testcommit2478
1646 = [up to date] testcommit2479 -> origin/testcommit2479
1647 = [up to date] testcommit248 -> origin/testcommit248
1648 = [up to date] testcommit2480 -> origin/testcommit2480
1649 = [up to date] testcommit2481 -> origin/testcommit2481
1650 = [up to date] testcommit2482 -> origin/testcommit2482
1651 = [up to date] testcommit2483 -> origin/testcommit2483
1652 = [up to date] testcommit2484 -> origin/testcommit2484
1653 = [up to date] testcommit2485 -> origin/testcommit2485
1654 = [up to date] testcommit2486 -> origin/testcommit2486
1655 = [up to date] testcommit2487 -> origin/testcommit2487
1656 = [up to date] testcommit2488 -> origin/testcommit2488
1657 = [up to date] testcommit2489 -> origin/testcommit2489
1658 = [up to date] testcommit249 -> origin/testcommit249
1659 = [up to date] testcommit2490 -> origin/testcommit2490
1660 = [up to date] testcommit2491 -> origin/testcommit2491
1661 = [up to date] testcommit2492 -> origin/testcommit2492
1662 = [up to date] testcommit2493 -> origin/testcommit2493
1663 = [up to date] testcommit2494 -> origin/testcommit2494
1664 = [up to date] testcommit2495 -> origin/testcommit2495
1665 = [up to date] testcommit2496 -> origin/testcommit2496
1666 = [up to date] testcommit2497 -> origin/testcommit2497
1667 = [up to date] testcommit2498 -> origin/testcommit2498
1668 = [up to date] testcommit2499 -> origin/testcommit2499
1669 = [up to date] testcommit25 -> origin/testcommit25
1670 = [up to date] testcommit250 -> origin/testcommit250
1671 = [up to date] testcommit2500 -> origin/testcommit2500
1672 = [up to date] testcommit2501 -> origin/testcommit2501
1673 = [up to date] testcommit2502 -> origin/testcommit2502
1674 = [up to date] testcommit2503 -> origin/testcommit2503
1675 = [up to date] testcommit2504 -> origin/testcommit2504
1676 = [up to date] testcommit2505 -> origin/testcommit2505
1677 = [up to date] testcommit2506 -> origin/testcommit2506
1678 = [up to date] testcommit2507 -> origin/testcommit2507
1679 = [up to date] testcommit2508 -> origin/testcommit2508
1680 = [up to date] testcommit2509 -> origin/testcommit2509
1681 = [up to date] testcommit251 -> origin/testcommit251
1682 = [up to date] testcommit2510 -> origin/testcommit2510
1683 = [up to date] testcommit2511 -> origin/testcommit2511
1684 = [up to date] testcommit2512 -> origin/testcommit2512
1685 = [up to date] testcommit2513 -> origin/testcommit2513
1686 = [up to date] testcommit2514 -> origin/testcommit2514
1687 = [up to date] testcommit2515 -> origin/testcommit2515
1688 = [up to date] testcommit2516 -> origin/testcommit2516
1689 = [up to date] testcommit2517 -> origin/testcommit2517
1690 = [up to date] testcommit2518 -> origin/testcommit2518
1691 = [up to date] testcommit2519 -> origin/testcommit2519
1692 = [up to date] testcommit252 -> origin/testcommit252
1693 = [up to date] testcommit2520 -> origin/testcommit2520
1694 = [up to date] testcommit2521 -> origin/testcommit2521
1695 = [up to date] testcommit2522 -> origin/testcommit2522
1696 = [up to date] testcommit2523 -> origin/testcommit2523
1697 = [up to date] testcommit2524 -> origin/testcommit2524
1698 = [up to date] testcommit2525 -> origin/testcommit2525
1699 = [up to date] testcommit2526 -> origin/testcommit2526
1700 = [up to date] testcommit2527 -> origin/testcommit2527
1701 = [up to date] testcommit2528 -> origin/testcommit2528
1702 = [up to date] testcommit2529 -> origin/testcommit2529
1703 = [up to date] testcommit253 -> origin/testcommit253
1704 = [up to date] testcommit2530 -> origin/testcommit2530
1705 = [up to date] testcommit2531 -> origin/testcommit2531
1706 = [up to date] testcommit2532 -> origin/testcommit2532
1707 = [up to date] testcommit2533 -> origin/testcommit2533
1708 = [up to date] testcommit2534 -> origin/testcommit2534
1709 = [up to date] testcommit2535 -> origin/testcommit2535
1710 = [up to date] testcommit2536 -> origin/testcommit2536
1711 = [up to date] testcommit2537 -> origin/testcommit2537
1712 = [up to date] testcommit2538 -> origin/testcommit2538
1713 = [up to date] testcommit2539 -> origin/testcommit2539
1714 = [up to date] testcommit254 -> origin/testcommit254
1715 = [up to date] testcommit2540 -> origin/testcommit2540
1716 = [up to date] testcommit2541 -> origin/testcommit2541
1717 = [up to date] testcommit2542 -> origin/testcommit2542
1718 = [up to date] testcommit2543 -> origin/testcommit2543
1719 = [up to date] testcommit2544 -> origin/testcommit2544
1720 = [up to date] testcommit2545 -> origin/testcommit2545
1721 = [up to date] testcommit2546 -> origin/testcommit2546
1722 = [up to date] testcommit2547 -> origin/testcommit2547
1723 = [up to date] testcommit2548 -> origin/testcommit2548
1724 = [up to date] testcommit2549 -> origin/testcommit2549
1725 = [up to date] testcommit255 -> origin/testcommit255
1726 = [up to date] testcommit2550 -> origin/testcommit2550
1727 = [up to date] testcommit2551 -> origin/testcommit2551
1728 = [up to date] testcommit2552 -> origin/testcommit2552
1729 = [up to date] testcommit2553 -> origin/testcommit2553
1730 = [up to date] testcommit2554 -> origin/testcommit2554
1731 = [up to date] testcommit2555 -> origin/testcommit2555
1732 = [up to date] testcommit2556 -> origin/testcommit2556
1733 = [up to date] testcommit2557 -> origin/testcommit2557
1734 = [up to date] testcommit2558 -> origin/testcommit2558
1735 = [up to date] testcommit2559 -> origin/testcommit2559
1736 = [up to date] testcommit256 -> origin/testcommit256
1737 = [up to date] testcommit2560 -> origin/testcommit2560
1738 = [up to date] testcommit2561 -> origin/testcommit2561
1739 = [up to date] testcommit2562 -> origin/testcommit2562
1740 = [up to date] testcommit2563 -> origin/testcommit2563
1741 = [up to date] testcommit2564 -> origin/testcommit2564
1742 = [up to date] testcommit2565 -> origin/testcommit2565
1743 = [up to date] testcommit2566 -> origin/testcommit2566
1744 = [up to date] testcommit2567 -> origin/testcommit2567
1745 = [up to date] testcommit2568 -> origin/testcommit2568
1746 = [up to date] testcommit2569 -> origin/testcommit2569
1747 = [up to date] testcommit257 -> origin/testcommit257
1748 = [up to date] testcommit2570 -> origin/testcommit2570
1749 = [up to date] testcommit2571 -> origin/testcommit2571
1750 = [up to date] testcommit2572 -> origin/testcommit2572
1751 = [up to date] testcommit2573 -> origin/testcommit2573
1752 = [up to date] testcommit2574 -> origin/testcommit2574
1753 = [up to date] testcommit2575 -> origin/testcommit2575
1754 = [up to date] testcommit2576 -> origin/testcommit2576
1755 = [up to date] testcommit2577 -> origin/testcommit2577
1756 = [up to date] testcommit2578 -> origin/testcommit2578
1757 = [up to date] testcommit2579 -> origin/testcommit2579
1758 = [up to date] testcommit258 -> origin/testcommit258
1759 = [up to date] testcommit2580 -> origin/testcommit2580
1760 = [up to date] testcommit2581 -> origin/testcommit2581
1761 = [up to date] testcommit2582 -> origin/testcommit2582
1762 = [up to date] testcommit2583 -> origin/testcommit2583
1763 = [up to date] testcommit2584 -> origin/testcommit2584
1764 = [up to date] testcommit2585 -> origin/testcommit2585
1765 = [up to date] testcommit2586 -> origin/testcommit2586
1766 = [up to date] testcommit2587 -> origin/testcommit2587
1767 = [up to date] testcommit2588 -> origin/testcommit2588
1768 = [up to date] testcommit2589 -> origin/testcommit2589
1769 = [up to date] testcommit259 -> origin/testcommit259
1770 = [up to date] testcommit2590 -> origin/testcommit2590
1771 = [up to date] testcommit2591 -> origin/testcommit2591
1772 = [up to date] testcommit2592 -> origin/testcommit2592
1773 = [up to date] testcommit2593 -> origin/testcommit2593
1774 = [up to date] testcommit2594 -> origin/testcommit2594
1775 = [up to date] testcommit2595 -> origin/testcommit2595
1776 = [up to date] testcommit2596 -> origin/testcommit2596
1777 = [up to date] testcommit2597 -> origin/testcommit2597
1778 = [up to date] testcommit2598 -> origin/testcommit2598
1779 = [up to date] testcommit2599 -> origin/testcommit2599
1780 = [up to date] testcommit26 -> origin/testcommit26
1781 = [up to date] testcommit260 -> origin/testcommit260
1782 = [up to date] testcommit2600 -> origin/testcommit2600
1783 = [up to date] testcommit2601 -> origin/testcommit2601
1784 = [up to date] testcommit2602 -> origin/testcommit2602
1785 = [up to date] testcommit2603 -> origin/testcommit2603
1786 = [up to date] testcommit2604 -> origin/testcommit2604
1787 = [up to date] testcommit2605 -> origin/testcommit2605
1788 = [up to date] testcommit2606 -> origin/testcommit2606
1789 = [up to date] testcommit2607 -> origin/testcommit2607
1790 = [up to date] testcommit2608 -> origin/testcommit2608
1791 = [up to date] testcommit2609 -> origin/testcommit2609
1792 = [up to date] testcommit261 -> origin/testcommit261
1793 = [up to date] testcommit2610 -> origin/testcommit2610
1794 = [up to date] testcommit2611 -> origin/testcommit2611
1795 = [up to date] testcommit2612 -> origin/testcommit2612
1796 = [up to date] testcommit2613 -> origin/testcommit2613
1797 = [up to date] testcommit2614 -> origin/testcommit2614
1798 = [up to date] testcommit2615 -> origin/testcommit2615
1799 = [up to date] testcommit2616 -> origin/testcommit2616
1800 = [up to date] testcommit2617 -> origin/testcommit2617
1801 = [up to date] testcommit2618 -> origin/testcommit2618
1802 = [up to date] testcommit2619 -> origin/testcommit2619
1803 = [up to date] testcommit262 -> origin/testcommit262
1804 = [up to date] testcommit2620 -> origin/testcommit2620
1805 = [up to date] testcommit2621 -> origin/testcommit2621
1806 = [up to date] testcommit2622 -> origin/testcommit2622
1807 = [up to date] testcommit2623 -> origin/testcommit2623
1808 = [up to date] testcommit2624 -> origin/testcommit2624
1809 = [up to date] testcommit2625 -> origin/testcommit2625
1810 = [up to date] testcommit2626 -> origin/testcommit2626
1811 = [up to date] testcommit2627 -> origin/testcommit2627
1812 = [up to date] testcommit2628 -> origin/testcommit2628
1813 = [up to date] testcommit2629 -> origin/testcommit2629
1814 = [up to date] testcommit263 -> origin/testcommit263
1815 = [up to date] testcommit2630 -> origin/testcommit2630
1816 = [up to date] testcommit2631 -> origin/testcommit2631
1817 = [up to date] testcommit2632 -> origin/testcommit2632
1818 = [up to date] testcommit2633 -> origin/testcommit2633
1819 = [up to date] testcommit2634 -> origin/testcommit2634
1820 = [up to date] testcommit2635 -> origin/testcommit2635
1821 = [up to date] testcommit2636 -> origin/testcommit2636
1822 = [up to date] testcommit2637 -> origin/testcommit2637
1823 = [up to date] testcommit2638 -> origin/testcommit2638
1824 = [up to date] testcommit2639 -> origin/testcommit2639
1825 = [up to date] testcommit264 -> origin/testcommit264
1826 = [up to date] testcommit2640 -> origin/testcommit2640
1827 = [up to date] testcommit2641 -> origin/testcommit2641
1828 = [up to date] testcommit2642 -> origin/testcommit2642
1829 = [up to date] testcommit2643 -> origin/testcommit2643
1830 = [up to date] testcommit2644 -> origin/testcommit2644
1831 = [up to date] testcommit2645 -> origin/testcommit2645
1832 = [up to date] testcommit2646 -> origin/testcommit2646
1833 = [up to date] testcommit2647 -> origin/testcommit2647
1834 = [up to date] testcommit2648 -> origin/testcommit2648
1835 = [up to date] testcommit2649 -> origin/testcommit2649
1836 = [up to date] testcommit265 -> origin/testcommit265
1837 = [up to date] testcommit2650 -> origin/testcommit2650
1838 = [up to date] testcommit2651 -> origin/testcommit2651
1839 = [up to date] testcommit2652 -> origin/testcommit2652
1840 = [up to date] testcommit2653 -> origin/testcommit2653
1841 = [up to date] testcommit2654 -> origin/testcommit2654
1842 = [up to date] testcommit2655 -> origin/testcommit2655
1843 = [up to date] testcommit2656 -> origin/testcommit2656
1844 = [up to date] testcommit2657 -> origin/testcommit2657
1845 = [up to date] testcommit2658 -> origin/testcommit2658
1846 = [up to date] testcommit2659 -> origin/testcommit2659
1847 = [up to date] testcommit266 -> origin/testcommit266
1848 = [up to date] testcommit2660 -> origin/testcommit2660
1849 = [up to date] testcommit2661 -> origin/testcommit2661
1850 = [up to date] testcommit2662 -> origin/testcommit2662
1851 = [up to date] testcommit2663 -> origin/testcommit2663
1852 = [up to date] testcommit2664 -> origin/testcommit2664
1853 = [up to date] testcommit2665 -> origin/testcommit2665
1854 = [up to date] testcommit2666 -> origin/testcommit2666
1855 = [up to date] testcommit2667 -> origin/testcommit2667
1856 = [up to date] testcommit2668 -> origin/testcommit2668
1857 = [up to date] testcommit2669 -> origin/testcommit2669
1858 = [up to date] testcommit267 -> origin/testcommit267
1859 = [up to date] testcommit2670 -> origin/testcommit2670
1860 = [up to date] testcommit2671 -> origin/testcommit2671
1861 = [up to date] testcommit2672 -> origin/testcommit2672
1862 = [up to date] testcommit2673 -> origin/testcommit2673
1863 = [up to date] testcommit2674 -> origin/testcommit2674
1864 = [up to date] testcommit2675 -> origin/testcommit2675
1865 = [up to date] testcommit2676 -> origin/testcommit2676
1866 = [up to date] testcommit2677 -> origin/testcommit2677
1867 = [up to date] testcommit2678 -> origin/testcommit2678
1868 = [up to date] testcommit2679 -> origin/testcommit2679
1869 = [up to date] testcommit268 -> origin/testcommit268
1870 = [up to date] testcommit2680 -> origin/testcommit2680
1871 = [up to date] testcommit2681 -> origin/testcommit2681
1872 = [up to date] testcommit2682 -> origin/testcommit2682
1873 = [up to date] testcommit2683 -> origin/testcommit2683
1874 = [up to date] testcommit2684 -> origin/testcommit2684
1875 = [up to date] testcommit2685 -> origin/testcommit2685
1876 = [up to date] testcommit2686 -> origin/testcommit2686
1877 = [up to date] testcommit2687 -> origin/testcommit2687
1878 = [up to date] testcommit2688 -> origin/testcommit2688
1879 = [up to date] testcommit2689 -> origin/testcommit2689
1880 = [up to date] testcommit269 -> origin/testcommit269
1881 = [up to date] testcommit2690 -> origin/testcommit2690
1882 = [up to date] testcommit2691 -> origin/testcommit2691
1883 = [up to date] testcommit2692 -> origin/testcommit2692
1884 = [up to date] testcommit2693 -> origin/testcommit2693
1885 = [up to date] testcommit2694 -> origin/testcommit2694
1886 = [up to date] testcommit2695 -> origin/testcommit2695
1887 = [up to date] testcommit2696 -> origin/testcommit2696
1888 = [up to date] testcommit2697 -> origin/testcommit2697
1889 = [up to date] testcommit2698 -> origin/testcommit2698
1890 = [up to date] testcommit2699 -> origin/testcommit2699
1891 = [up to date] testcommit27 -> origin/testcommit27
1892 = [up to date] testcommit270 -> origin/testcommit270
1893 = [up to date] testcommit2700 -> origin/testcommit2700
1894 = [up to date] testcommit2701 -> origin/testcommit2701
1895 = [up to date] testcommit2702 -> origin/testcommit2702
1896 = [up to date] testcommit2703 -> origin/testcommit2703
1897 = [up to date] testcommit2704 -> origin/testcommit2704
1898 = [up to date] testcommit2705 -> origin/testcommit2705
1899 = [up to date] testcommit2706 -> origin/testcommit2706
1900 = [up to date] testcommit2707 -> origin/testcommit2707
1901 = [up to date] testcommit2708 -> origin/testcommit2708
1902 = [up to date] testcommit2709 -> origin/testcommit2709
1903 = [up to date] testcommit271 -> origin/testcommit271
1904 = [up to date] testcommit2710 -> origin/testcommit2710
1905 = [up to date] testcommit2711 -> origin/testcommit2711
1906 = [up to date] testcommit2712 -> origin/testcommit2712
1907 = [up to date] testcommit2713 -> origin/testcommit2713
1908 = [up to date] testcommit2714 -> origin/testcommit2714
1909 = [up to date] testcommit2715 -> origin/testcommit2715
1910 = [up to date] testcommit2716 -> origin/testcommit2716
1911 = [up to date] testcommit2717 -> origin/testcommit2717
1912 = [up to date] testcommit2718 -> origin/testcommit2718
1913 = [up to date] testcommit2719 -> origin/testcommit2719
1914 = [up to date] testcommit272 -> origin/testcommit272
1915 = [up to date] testcommit2720 -> origin/testcommit2720
1916 = [up to date] testcommit2721 -> origin/testcommit2721
1917 = [up to date] testcommit2722 -> origin/testcommit2722
1918 = [up to date] testcommit2723 -> origin/testcommit2723
1919 = [up to date] testcommit2724 -> origin/testcommit2724
1920 = [up to date] testcommit2725 -> origin/testcommit2725
1921 = [up to date] testcommit2726 -> origin/testcommit2726
1922 = [up to date] testcommit2727 -> origin/testcommit2727
1923 = [up to date] testcommit2728 -> origin/testcommit2728
1924 = [up to date] testcommit2729 -> origin/testcommit2729
1925 = [up to date] testcommit273 -> origin/testcommit273
1926 = [up to date] testcommit2730 -> origin/testcommit2730
1927 = [up to date] testcommit2731 -> origin/testcommit2731
1928 = [up to date] testcommit2732 -> origin/testcommit2732
1929 = [up to date] testcommit2733 -> origin/testcommit2733
1930 = [up to date] testcommit2734 -> origin/testcommit2734
1931 = [up to date] testcommit2735 -> origin/testcommit2735
1932 = [up to date] testcommit2736 -> origin/testcommit2736
1933 = [up to date] testcommit2737 -> origin/testcommit2737
1934 = [up to date] testcommit2738 -> origin/testcommit2738
1935 = [up to date] testcommit2739 -> origin/testcommit2739
1936 = [up to date] testcommit274 -> origin/testcommit274
1937 = [up to date] testcommit2740 -> origin/testcommit2740
1938 = [up to date] testcommit2741 -> origin/testcommit2741
1939 = [up to date] testcommit2742 -> origin/testcommit2742
1940 = [up to date] testcommit2743 -> origin/testcommit2743
1941 = [up to date] testcommit2744 -> origin/testcommit2744
1942 = [up to date] testcommit2745 -> origin/testcommit2745
1943 = [up to date] testcommit2746 -> origin/testcommit2746
1944 = [up to date] testcommit2747 -> origin/testcommit2747
1945 = [up to date] testcommit2748 -> origin/testcommit2748
1946 = [up to date] testcommit2749 -> origin/testcommit2749
1947 = [up to date] testcommit275 -> origin/testcommit275
1948 = [up to date] testcommit2750 -> origin/testcommit2750
1949 = [up to date] testcommit2751 -> origin/testcommit2751
1950 = [up to date] testcommit2752 -> origin/testcommit2752
1951 = [up to date] testcommit2753 -> origin/testcommit2753
1952 = [up to date] testcommit2754 -> origin/testcommit2754
1953 = [up to date] testcommit2755 -> origin/testcommit2755
1954 = [up to date] testcommit2756 -> origin/testcommit2756
1955 = [up to date] testcommit2757 -> origin/testcommit2757
1956 = [up to date] testcommit2758 -> origin/testcommit2758
1957 = [up to date] testcommit2759 -> origin/testcommit2759
1958 = [up to date] testcommit276 -> origin/testcommit276
1959 = [up to date] testcommit2760 -> origin/testcommit2760
1960 = [up to date] testcommit2761 -> origin/testcommit2761
1961 = [up to date] testcommit2762 -> origin/testcommit2762
1962 = [up to date] testcommit2763 -> origin/testcommit2763
1963 = [up to date] testcommit2764 -> origin/testcommit2764
1964 = [up to date] testcommit2765 -> origin/testcommit2765
1965 = [up to date] testcommit2766 -> origin/testcommit2766
1966 = [up to date] testcommit2767 -> origin/testcommit2767
1967 = [up to date] testcommit2768 -> origin/testcommit2768
1968 = [up to date] testcommit2769 -> origin/testcommit2769
1969 = [up to date] testcommit277 -> origin/testcommit277
1970 = [up to date] testcommit2770 -> origin/testcommit2770
1971 = [up to date] testcommit2771 -> origin/testcommit2771
1972 = [up to date] testcommit2772 -> origin/testcommit2772
1973 = [up to date] testcommit2773 -> origin/testcommit2773
1974 = [up to date] testcommit2774 -> origin/testcommit2774
1975 = [up to date] testcommit2775 -> origin/testcommit2775
1976 = [up to date] testcommit2776 -> origin/testcommit2776
1977 = [up to date] testcommit2777 -> origin/testcommit2777
1978 = [up to date] testcommit2778 -> origin/testcommit2778
1979 = [up to date] testcommit2779 -> origin/testcommit2779
1980 = [up to date] testcommit278 -> origin/testcommit278
1981 = [up to date] testcommit2780 -> origin/testcommit2780
1982 = [up to date] testcommit2781 -> origin/testcommit2781
1983 = [up to date] testcommit2782 -> origin/testcommit2782
1984 = [up to date] testcommit2783 -> origin/testcommit2783
1985 = [up to date] testcommit2784 -> origin/testcommit2784
1986 = [up to date] testcommit2785 -> origin/testcommit2785
1987 = [up to date] testcommit2786 -> origin/testcommit2786
1988 = [up to date] testcommit2787 -> origin/testcommit2787
1989 = [up to date] testcommit2788 -> origin/testcommit2788
1990 = [up to date] testcommit2789 -> origin/testcommit2789
1991 = [up to date] testcommit279 -> origin/testcommit279
1992 = [up to date] testcommit2790 -> origin/testcommit2790
1993 = [up to date] testcommit2791 -> origin/testcommit2791
1994 = [up to date] testcommit2792 -> origin/testcommit2792
1995 = [up to date] testcommit2793 -> origin/testcommit2793
1996 = [up to date] testcommit2794 -> origin/testcommit2794
1997 = [up to date] testcommit2795 -> origin/testcommit2795
1998 = [up to date] testcommit2796 -> origin/testcommit2796
1999 = [up to date] testcommit2797 -> origin/testcommit2797
2000 = [up to date] testcommit2798 -> origin/testcommit2798
2001 = [up to date] testcommit2799 -> origin/testcommit2799
2002 = [up to date] testcommit28 -> origin/testcommit28
2003 = [up to date] testcommit280 -> origin/testcommit280
2004 = [up to date] testcommit2800 -> origin/testcommit2800
2005 = [up to date] testcommit2801 -> origin/testcommit2801
2006 = [up to date] testcommit2802 -> origin/testcommit2802
2007 = [up to date] testcommit2803 -> origin/testcommit2803
2008 = [up to date] testcommit2804 -> origin/testcommit2804
2009 = [up to date] testcommit2805 -> origin/testcommit2805
2010 = [up to date] testcommit2806 -> origin/testcommit2806
2011 = [up to date] testcommit2807 -> origin/testcommit2807
2012 = [up to date] testcommit2808 -> origin/testcommit2808
2013 = [up to date] testcommit2809 -> origin/testcommit2809
2014 = [up to date] testcommit281 -> origin/testcommit281
2015 = [up to date] testcommit2810 -> origin/testcommit2810
2016 = [up to date] testcommit2811 -> origin/testcommit2811
2017 = [up to date] testcommit2812 -> origin/testcommit2812
2018 = [up to date] testcommit2813 -> origin/testcommit2813
2019 = [up to date] testcommit2814 -> origin/testcommit2814
2020 = [up to date] testcommit2815 -> origin/testcommit2815
2021 = [up to date] testcommit2816 -> origin/testcommit2816
2022 = [up to date] testcommit2817 -> origin/testcommit2817
2023 = [up to date] testcommit2818 -> origin/testcommit2818
2024 = [up to date] testcommit2819 -> origin/testcommit2819
2025 = [up to date] testcommit282 -> origin/testcommit282
2026 = [up to date] testcommit2820 -> origin/testcommit2820
2027 = [up to date] testcommit2821 -> origin/testcommit2821
2028 = [up to date] testcommit2822 -> origin/testcommit2822
2029 = [up to date] testcommit2823 -> origin/testcommit2823
2030 = [up to date] testcommit2824 -> origin/testcommit2824
2031 = [up to date] testcommit2825 -> origin/testcommit2825
2032 = [up to date] testcommit2826 -> origin/testcommit2826
2033 = [up to date] testcommit2827 -> origin/testcommit2827
2034 = [up to date] testcommit2828 -> origin/testcommit2828
2035 = [up to date] testcommit2829 -> origin/testcommit2829
2036 = [up to date] testcommit283 -> origin/testcommit283
2037 = [up to date] testcommit2830 -> origin/testcommit2830
2038 = [up to date] testcommit2831 -> origin/testcommit2831
2039 = [up to date] testcommit2832 -> origin/testcommit2832
2040 = [up to date] testcommit2833 -> origin/testcommit2833
2041 = [up to date] testcommit2834 -> origin/testcommit2834
2042 = [up to date] testcommit2835 -> origin/testcommit2835
2043 = [up to date] testcommit2836 -> origin/testcommit2836
2044 = [up to date] testcommit2837 -> origin/testcommit2837
2045 = [up to date] testcommit2838 -> origin/testcommit2838
2046 = [up to date] testcommit2839 -> origin/testcommit2839
2047 = [up to date] testcommit284 -> origin/testcommit284
2048 = [up to date] testcommit2840 -> origin/testcommit2840
2049 = [up to date] testcommit2841 -> origin/testcommit2841
2050 = [up to date] testcommit2842 -> origin/testcommit2842
2051 = [up to date] testcommit2843 -> origin/testcommit2843
2052 = [up to date] testcommit2844 -> origin/testcommit2844
2053 = [up to date] testcommit2845 -> origin/testcommit2845
2054 = [up to date] testcommit2846 -> origin/testcommit2846
2055 = [up to date] testcommit2847 -> origin/testcommit2847
2056 = [up to date] testcommit2848 -> origin/testcommit2848
2057 = [up to date] testcommit2849 -> origin/testcommit2849
2058 = [up to date] testcommit285 -> origin/testcommit285
2059 = [up to date] testcommit2850 -> origin/testcommit2850
2060 = [up to date] testcommit2851 -> origin/testcommit2851
2061 = [up to date] testcommit2852 -> origin/testcommit2852
2062 = [up to date] testcommit2853 -> origin/testcommit2853
2063 = [up to date] testcommit2854 -> origin/testcommit2854
2064 = [up to date] testcommit2855 -> origin/testcommit2855
2065 = [up to date] testcommit2856 -> origin/testcommit2856
2066 = [up to date] testcommit2857 -> origin/testcommit2857
2067 = [up to date] testcommit2858 -> origin/testcommit2858
2068 = [up to date] testcommit2859 -> origin/testcommit2859
2069 = [up to date] testcommit286 -> origin/testcommit286
2070 = [up to date] testcommit2860 -> origin/testcommit2860
2071 = [up to date] testcommit2861 -> origin/testcommit2861
2072 = [up to date] testcommit2862 -> origin/testcommit2862
2073 = [up to date] testcommit2863 -> origin/testcommit2863
2074 = [up to date] testcommit2864 -> origin/testcommit2864
2075 = [up to date] testcommit2865 -> origin/testcommit2865
2076 = [up to date] testcommit2866 -> origin/testcommit2866
2077 = [up to date] testcommit2867 -> origin/testcommit2867
2078 = [up to date] testcommit2868 -> origin/testcommit2868
2079 = [up to date] testcommit2869 -> origin/testcommit2869
2080 = [up to date] testcommit287 -> origin/testcommit287
2081 = [up to date] testcommit2870 -> origin/testcommit2870
2082 = [up to date] testcommit2871 -> origin/testcommit2871
2083 = [up to date] testcommit2872 -> origin/testcommit2872
2084 = [up to date] testcommit2873 -> origin/testcommit2873
2085 = [up to date] testcommit2874 -> origin/testcommit2874
2086 = [up to date] testcommit2875 -> origin/testcommit2875
2087 = [up to date] testcommit2876 -> origin/testcommit2876
2088 = [up to date] testcommit2877 -> origin/testcommit2877
2089 = [up to date] testcommit2878 -> origin/testcommit2878
2090 = [up to date] testcommit2879 -> origin/testcommit2879
2091 = [up to date] testcommit288 -> origin/testcommit288
2092 = [up to date] testcommit2880 -> origin/testcommit2880
2093 = [up to date] testcommit2881 -> origin/testcommit2881
2094 = [up to date] testcommit2882 -> origin/testcommit2882
2095 = [up to date] testcommit2883 -> origin/testcommit2883
2096 = [up to date] testcommit2884 -> origin/testcommit2884
2097 = [up to date] testcommit2885 -> origin/testcommit2885
2098 = [up to date] testcommit2886 -> origin/testcommit2886
2099 = [up to date] testcommit2887 -> origin/testcommit2887
2100 = [up to date] testcommit2888 -> origin/testcommit2888
2101 = [up to date] testcommit2889 -> origin/testcommit2889
2102 = [up to date] testcommit289 -> origin/testcommit289
2103 = [up to date] testcommit2890 -> origin/testcommit2890
2104 = [up to date] testcommit2891 -> origin/testcommit2891
2105 = [up to date] testcommit2892 -> origin/testcommit2892
2106 = [up to date] testcommit2893 -> origin/testcommit2893
2107 = [up to date] testcommit2894 -> origin/testcommit2894
2108 = [up to date] testcommit2895 -> origin/testcommit2895
2109 = [up to date] testcommit2896 -> origin/testcommit2896
2110 = [up to date] testcommit2897 -> origin/testcommit2897
2111 = [up to date] testcommit2898 -> origin/testcommit2898
2112 = [up to date] testcommit2899 -> origin/testcommit2899
2113 = [up to date] testcommit29 -> origin/testcommit29
2114 = [up to date] testcommit290 -> origin/testcommit290
2115 = [up to date] testcommit2900 -> origin/testcommit2900
2116 = [up to date] testcommit2901 -> origin/testcommit2901
2117 = [up to date] testcommit2902 -> origin/testcommit2902
2118 = [up to date] testcommit2903 -> origin/testcommit2903
2119 = [up to date] testcommit2904 -> origin/testcommit2904
2120 = [up to date] testcommit2905 -> origin/testcommit2905
2121 = [up to date] testcommit2906 -> origin/testcommit2906
2122 = [up to date] testcommit2907 -> origin/testcommit2907
2123 = [up to date] testcommit2908 -> origin/testcommit2908
2124 = [up to date] testcommit2909 -> origin/testcommit2909
2125 = [up to date] testcommit291 -> origin/testcommit291
2126 = [up to date] testcommit2910 -> origin/testcommit2910
2127 = [up to date] testcommit2911 -> origin/testcommit2911
2128 = [up to date] testcommit2912 -> origin/testcommit2912
2129 = [up to date] testcommit2913 -> origin/testcommit2913
2130 = [up to date] testcommit2914 -> origin/testcommit2914
2131 = [up to date] testcommit2915 -> origin/testcommit2915
2132 = [up to date] testcommit2916 -> origin/testcommit2916
2133 = [up to date] testcommit2917 -> origin/testcommit2917
2134 = [up to date] testcommit2918 -> origin/testcommit2918
2135 = [up to date] testcommit2919 -> origin/testcommit2919
2136 = [up to date] testcommit292 -> origin/testcommit292
2137 = [up to date] testcommit2920 -> origin/testcommit2920
2138 = [up to date] testcommit2921 -> origin/testcommit2921
2139 = [up to date] testcommit2922 -> origin/testcommit2922
2140 = [up to date] testcommit2923 -> origin/testcommit2923
2141 = [up to date] testcommit2924 -> origin/testcommit2924
2142 = [up to date] testcommit2925 -> origin/testcommit2925
2143 = [up to date] testcommit2926 -> origin/testcommit2926
2144 = [up to date] testcommit2927 -> origin/testcommit2927
2145 = [up to date] testcommit2928 -> origin/testcommit2928
2146 = [up to date] testcommit2929 -> origin/testcommit2929
2147 = [up to date] testcommit293 -> origin/testcommit293
2148 = [up to date] testcommit2930 -> origin/testcommit2930
2149 = [up to date] testcommit2931 -> origin/testcommit2931
2150 = [up to date] testcommit2932 -> origin/testcommit2932
2151 = [up to date] testcommit2933 -> origin/testcommit2933
2152 = [up to date] testcommit2934 -> origin/testcommit2934
2153 = [up to date] testcommit2935 -> origin/testcommit2935
2154 = [up to date] testcommit2936 -> origin/testcommit2936
2155 = [up to date] testcommit2937 -> origin/testcommit2937
2156 = [up to date] testcommit2938 -> origin/testcommit2938
2157 = [up to date] testcommit2939 -> origin/testcommit2939
2158 = [up to date] testcommit294 -> origin/testcommit294
2159 = [up to date] testcommit2940 -> origin/testcommit2940
2160 = [up to date] testcommit2941 -> origin/testcommit2941
2161 = [up to date] testcommit2942 -> origin/testcommit2942
2162 = [up to date] testcommit2943 -> origin/testcommit2943
2163 = [up to date] testcommit2944 -> origin/testcommit2944
2164 = [up to date] testcommit2945 -> origin/testcommit2945
2165 = [up to date] testcommit2946 -> origin/testcommit2946
2166 = [up to date] testcommit2947 -> origin/testcommit2947
2167 = [up to date] testcommit2948 -> origin/testcommit2948
2168 = [up to date] testcommit2949 -> origin/testcommit2949
2169 = [up to date] testcommit295 -> origin/testcommit295
2170 = [up to date] testcommit2950 -> origin/testcommit2950
2171 = [up to date] testcommit2951 -> origin/testcommit2951
2172 = [up to date] testcommit2952 -> origin/testcommit2952
2173 = [up to date] testcommit2953 -> origin/testcommit2953
2174 = [up to date] testcommit2954 -> origin/testcommit2954
2175 = [up to date] testcommit2955 -> origin/testcommit2955
2176 = [up to date] testcommit2956 -> origin/testcommit2956
2177 = [up to date] testcommit2957 -> origin/testcommit2957
2178 = [up to date] testcommit2958 -> origin/testcommit2958
2179 = [up to date] testcommit2959 -> origin/testcommit2959
2180 = [up to date] testcommit296 -> origin/testcommit296
2181 = [up to date] testcommit2960 -> origin/testcommit2960
2182 = [up to date] testcommit2961 -> origin/testcommit2961
2183 = [up to date] testcommit2962 -> origin/testcommit2962
2184 = [up to date] testcommit2963 -> origin/testcommit2963
2185 = [up to date] testcommit2964 -> origin/testcommit2964
2186 = [up to date] testcommit2965 -> origin/testcommit2965
2187 = [up to date] testcommit2966 -> origin/testcommit2966
2188 = [up to date] testcommit2967 -> origin/testcommit2967
2189 = [up to date] testcommit2968 -> origin/testcommit2968
2190 = [up to date] testcommit2969 -> origin/testcommit2969
2191 = [up to date] testcommit297 -> origin/testcommit297
2192 = [up to date] testcommit2970 -> origin/testcommit2970
2193 = [up to date] testcommit2971 -> origin/testcommit2971
2194 = [up to date] testcommit2972 -> origin/testcommit2972
2195 = [up to date] testcommit2973 -> origin/testcommit2973
2196 = [up to date] testcommit2974 -> origin/testcommit2974
2197 = [up to date] testcommit2975 -> origin/testcommit2975
2198 = [up to date] testcommit2976 -> origin/testcommit2976
2199 = [up to date] testcommit2977 -> origin/testcommit2977
2200 = [up to date] testcommit2978 -> origin/testcommit2978
2201 = [up to date] testcommit2979 -> origin/testcommit2979
2202 = [up to date] testcommit298 -> origin/testcommit298
2203 = [up to date] testcommit2980 -> origin/testcommit2980
2204 = [up to date] testcommit2981 -> origin/testcommit2981
2205 = [up to date] testcommit2982 -> origin/testcommit2982
2206 = [up to date] testcommit2983 -> origin/testcommit2983
2207 = [up to date] testcommit2984 -> origin/testcommit2984
2208 = [up to date] testcommit2985 -> origin/testcommit2985
2209 = [up to date] testcommit2986 -> origin/testcommit2986
2210 = [up to date] testcommit2987 -> origin/testcommit2987
2211 = [up to date] testcommit2988 -> origin/testcommit2988
2212 = [up to date] testcommit2989 -> origin/testcommit2989
2213 = [up to date] testcommit299 -> origin/testcommit299
2214 = [up to date] testcommit2990 -> origin/testcommit2990
2215 = [up to date] testcommit2991 -> origin/testcommit2991
2216 = [up to date] testcommit2992 -> origin/testcommit2992
2217 = [up to date] testcommit2993 -> origin/testcommit2993
2218 = [up to date] testcommit2994 -> origin/testcommit2994
2219 = [up to date] testcommit2995 -> origin/testcommit2995
2220 = [up to date] testcommit2996 -> origin/testcommit2996
2221 = [up to date] testcommit2997 -> origin/testcommit2997
2222 = [up to date] testcommit2998 -> origin/testcommit2998
2223 = [up to date] testcommit2999 -> origin/testcommit2999
2224 = [up to date] testcommit3 -> origin/testcommit3
2225 = [up to date] testcommit30 -> origin/testcommit30
2226 = [up to date] testcommit300 -> origin/testcommit300
2227 = [up to date] testcommit3000 -> origin/testcommit3000
2228 = [up to date] testcommit3001 -> origin/testcommit3001
2229 = [up to date] testcommit3002 -> origin/testcommit3002
2230 = [up to date] testcommit3003 -> origin/testcommit3003
2231 = [up to date] testcommit3004 -> origin/testcommit3004
2232 = [up to date] testcommit3005 -> origin/testcommit3005
2233 = [up to date] testcommit3006 -> origin/testcommit3006
2234 = [up to date] testcommit3007 -> origin/testcommit3007
2235 = [up to date] testcommit3008 -> origin/testcommit3008
2236 = [up to date] testcommit3009 -> origin/testcommit3009
2237 = [up to date] testcommit301 -> origin/testcommit301
2238 = [up to date] testcommit3010 -> origin/testcommit3010
2239 = [up to date] testcommit3011 -> origin/testcommit3011
2240 = [up to date] testcommit3012 -> origin/testcommit3012
2241 = [up to date] testcommit3013 -> origin/testcommit3013
2242 = [up to date] testcommit3014 -> origin/testcommit3014
2243 = [up to date] testcommit3015 -> origin/testcommit3015
2244 = [up to date] testcommit3016 -> origin/testcommit3016
2245 = [up to date] testcommit3017 -> origin/testcommit3017
2246 = [up to date] testcommit3018 -> origin/testcommit3018
2247 = [up to date] testcommit3019 -> origin/testcommit3019
2248 = [up to date] testcommit302 -> origin/testcommit302
2249 = [up to date] testcommit3020 -> origin/testcommit3020
2250 = [up to date] testcommit3021 -> origin/testcommit3021
2251 = [up to date] testcommit3022 -> origin/testcommit3022
2252 = [up to date] testcommit3023 -> origin/testcommit3023
2253 = [up to date] testcommit3024 -> origin/testcommit3024
2254 = [up to date] testcommit3025 -> origin/testcommit3025
2255 = [up to date] testcommit3026 -> origin/testcommit3026
2256 = [up to date] testcommit3027 -> origin/testcommit3027
2257 = [up to date] testcommit3028 -> origin/testcommit3028
2258 = [up to date] testcommit3029 -> origin/testcommit3029
2259 = [up to date] testcommit303 -> origin/testcommit303
2260 = [up to date] testcommit3030 -> origin/testcommit3030
2261 = [up to date] testcommit3031 -> origin/testcommit3031
2262 = [up to date] testcommit3032 -> origin/testcommit3032
2263 = [up to date] testcommit3033 -> origin/testcommit3033
2264 = [up to date] testcommit3034 -> origin/testcommit3034
2265 = [up to date] testcommit3035 -> origin/testcommit3035
2266 = [up to date] testcommit3036 -> origin/testcommit3036
2267 = [up to date] testcommit3037 -> origin/testcommit3037
2268 = [up to date] testcommit3038 -> origin/testcommit3038
2269 = [up to date] testcommit3039 -> origin/testcommit3039
2270 = [up to date] testcommit304 -> origin/testcommit304
2271 = [up to date] testcommit3040 -> origin/testcommit3040
2272 = [up to date] testcommit3041 -> origin/testcommit3041
2273 = [up to date] testcommit3042 -> origin/testcommit3042
2274 = [up to date] testcommit3043 -> origin/testcommit3043
2275 = [up to date] testcommit3044 -> origin/testcommit3044
2276 = [up to date] testcommit3045 -> origin/testcommit3045
2277 = [up to date] testcommit3046 -> origin/testcommit3046
2278 = [up to date] testcommit3047 -> origin/testcommit3047
2279 = [up to date] testcommit3048 -> origin/testcommit3048
2280 = [up to date] testcommit3049 -> origin/testcommit3049
2281 = [up to date] testcommit305 -> origin/testcommit305
2282 = [up to date] testcommit3050 -> origin/testcommit3050
2283 = [up to date] testcommit3051 -> origin/testcommit3051
2284 = [up to date] testcommit3052 -> origin/testcommit3052
2285 = [up to date] testcommit3053 -> origin/testcommit3053
2286 = [up to date] testcommit3054 -> origin/testcommit3054
2287 = [up to date] testcommit3055 -> origin/testcommit3055
2288 = [up to date] testcommit3056 -> origin/testcommit3056
2289 = [up to date] testcommit3057 -> origin/testcommit3057
2290 = [up to date] testcommit3058 -> origin/testcommit3058
2291 = [up to date] testcommit3059 -> origin/testcommit3059
2292 = [up to date] testcommit306 -> origin/testcommit306
2293 = [up to date] testcommit3060 -> origin/testcommit3060
2294 = [up to date] testcommit3061 -> origin/testcommit3061
2295 = [up to date] testcommit3062 -> origin/testcommit3062
2296 = [up to date] testcommit3063 -> origin/testcommit3063
2297 = [up to date] testcommit3064 -> origin/testcommit3064
2298 = [up to date] testcommit3065 -> origin/testcommit3065
2299 = [up to date] testcommit3066 -> origin/testcommit3066
2300 = [up to date] testcommit3067 -> origin/testcommit3067
2301 = [up to date] testcommit3068 -> origin/testcommit3068
2302 = [up to date] testcommit3069 -> origin/testcommit3069
2303 = [up to date] testcommit307 -> origin/testcommit307
2304 = [up to date] testcommit3070 -> origin/testcommit3070
2305 = [up to date] testcommit3071 -> origin/testcommit3071
2306 = [up to date] testcommit3072 -> origin/testcommit3072
2307 = [up to date] testcommit3073 -> origin/testcommit3073
2308 = [up to date] testcommit3074 -> origin/testcommit3074
2309 = [up to date] testcommit3075 -> origin/testcommit3075
2310 = [up to date] testcommit3076 -> origin/testcommit3076
2311 = [up to date] testcommit3077 -> origin/testcommit3077
2312 = [up to date] testcommit3078 -> origin/testcommit3078
2313 = [up to date] testcommit3079 -> origin/testcommit3079
2314 = [up to date] testcommit308 -> origin/testcommit308
2315 = [up to date] testcommit3080 -> origin/testcommit3080
2316 = [up to date] testcommit3081 -> origin/testcommit3081
2317 = [up to date] testcommit3082 -> origin/testcommit3082
2318 = [up to date] testcommit3083 -> origin/testcommit3083
2319 = [up to date] testcommit3084 -> origin/testcommit3084
2320 = [up to date] testcommit3085 -> origin/testcommit3085
2321 = [up to date] testcommit3086 -> origin/testcommit3086
2322 = [up to date] testcommit3087 -> origin/testcommit3087
2323 = [up to date] testcommit3088 -> origin/testcommit3088
2324 = [up to date] testcommit3089 -> origin/testcommit3089
2325 = [up to date] testcommit309 -> origin/testcommit309
2326 = [up to date] testcommit3090 -> origin/testcommit3090
2327 = [up to date] testcommit3091 -> origin/testcommit3091
2328 = [up to date] testcommit3092 -> origin/testcommit3092
2329 = [up to date] testcommit3093 -> origin/testcommit3093
2330 = [up to date] testcommit3094 -> origin/testcommit3094
2331 = [up to date] testcommit3095 -> origin/testcommit3095
2332 = [up to date] testcommit3096 -> origin/testcommit3096
2333 = [up to date] testcommit3097 -> origin/testcommit3097
2334 = [up to date] testcommit3098 -> origin/testcommit3098
2335 = [up to date] testcommit3099 -> origin/testcommit3099
2336 = [up to date] testcommit31 -> origin/testcommit31
2337 = [up to date] testcommit310 -> origin/testcommit310
2338 = [up to date] testcommit3100 -> origin/testcommit3100
2339 = [up to date] testcommit3101 -> origin/testcommit3101
2340 = [up to date] testcommit3102 -> origin/testcommit3102
2341 = [up to date] testcommit3103 -> origin/testcommit3103
2342 = [up to date] testcommit3104 -> origin/testcommit3104
2343 = [up to date] testcommit3105 -> origin/testcommit3105
2344 = [up to date] testcommit3106 -> origin/testcommit3106
2345 = [up to date] testcommit3107 -> origin/testcommit3107
2346 = [up to date] testcommit3108 -> origin/testcommit3108
2347 = [up to date] testcommit3109 -> origin/testcommit3109
2348 = [up to date] testcommit311 -> origin/testcommit311
2349 = [up to date] testcommit3110 -> origin/testcommit3110
2350 = [up to date] testcommit3111 -> origin/testcommit3111
2351 = [up to date] testcommit3112 -> origin/testcommit3112
2352 = [up to date] testcommit3113 -> origin/testcommit3113
2353 = [up to date] testcommit3114 -> origin/testcommit3114
2354 = [up to date] testcommit3115 -> origin/testcommit3115
2355 = [up to date] testcommit3116 -> origin/testcommit3116
2356 = [up to date] testcommit3117 -> origin/testcommit3117
2357 = [up to date] testcommit3118 -> origin/testcommit3118
2358 = [up to date] testcommit3119 -> origin/testcommit3119
2359 = [up to date] testcommit312 -> origin/testcommit312
2360 = [up to date] testcommit3120 -> origin/testcommit3120
2361 = [up to date] testcommit3121 -> origin/testcommit3121
2362 = [up to date] testcommit3122 -> origin/testcommit3122
2363 = [up to date] testcommit3123 -> origin/testcommit3123
2364 = [up to date] testcommit3124 -> origin/testcommit3124
2365 = [up to date] testcommit3125 -> origin/testcommit3125
2366 = [up to date] testcommit3126 -> origin/testcommit3126
2367 = [up to date] testcommit3127 -> origin/testcommit3127
2368 = [up to date] testcommit3128 -> origin/testcommit3128
2369 = [up to date] testcommit3129 -> origin/testcommit3129
2370 = [up to date] testcommit313 -> origin/testcommit313
2371 = [up to date] testcommit3130 -> origin/testcommit3130
2372 = [up to date] testcommit3131 -> origin/testcommit3131
2373 = [up to date] testcommit3132 -> origin/testcommit3132
2374 = [up to date] testcommit3133 -> origin/testcommit3133
2375 = [up to date] testcommit3134 -> origin/testcommit3134
2376 = [up to date] testcommit3135 -> origin/testcommit3135
2377 = [up to date] testcommit3136 -> origin/testcommit3136
2378 = [up to date] testcommit3137 -> origin/testcommit3137
2379 = [up to date] testcommit3138 -> origin/testcommit3138
2380 = [up to date] testcommit3139 -> origin/testcommit3139
2381 = [up to date] testcommit314 -> origin/testcommit314
2382 = [up to date] testcommit3140 -> origin/testcommit3140
2383 = [up to date] testcommit3141 -> origin/testcommit3141
2384 = [up to date] testcommit3142 -> origin/testcommit3142
2385 = [up to date] testcommit3143 -> origin/testcommit3143
2386 = [up to date] testcommit3144 -> origin/testcommit3144
2387 = [up to date] testcommit3145 -> origin/testcommit3145
2388 = [up to date] testcommit3146 -> origin/testcommit3146
2389 = [up to date] testcommit3147 -> origin/testcommit3147
2390 = [up to date] testcommit3148 -> origin/testcommit3148
2391 = [up to date] testcommit3149 -> origin/testcommit3149
2392 = [up to date] testcommit315 -> origin/testcommit315
2393 = [up to date] testcommit3150 -> origin/testcommit3150
2394 = [up to date] testcommit3151 -> origin/testcommit3151
2395 = [up to date] testcommit3152 -> origin/testcommit3152
2396 = [up to date] testcommit3153 -> origin/testcommit3153
2397 = [up to date] testcommit3154 -> origin/testcommit3154
2398 = [up to date] testcommit3155 -> origin/testcommit3155
2399 = [up to date] testcommit3156 -> origin/testcommit3156
2400 = [up to date] testcommit3157 -> origin/testcommit3157
2401 = [up to date] testcommit3158 -> origin/testcommit3158
2402 = [up to date] testcommit3159 -> origin/testcommit3159
2403 = [up to date] testcommit316 -> origin/testcommit316
2404 = [up to date] testcommit3160 -> origin/testcommit3160
2405 = [up to date] testcommit3161 -> origin/testcommit3161
2406 = [up to date] testcommit3162 -> origin/testcommit3162
2407 = [up to date] testcommit3163 -> origin/testcommit3163
2408 = [up to date] testcommit3164 -> origin/testcommit3164
2409 = [up to date] testcommit3165 -> origin/testcommit3165
2410 = [up to date] testcommit3166 -> origin/testcommit3166
2411 = [up to date] testcommit3167 -> origin/testcommit3167
2412 = [up to date] testcommit3168 -> origin/testcommit3168
2413 = [up to date] testcommit3169 -> origin/testcommit3169
2414 = [up to date] testcommit317 -> origin/testcommit317
2415 = [up to date] testcommit3170 -> origin/testcommit3170
2416 = [up to date] testcommit3171 -> origin/testcommit3171
2417 = [up to date] testcommit3172 -> origin/testcommit3172
2418 = [up to date] testcommit3173 -> origin/testcommit3173
2419 = [up to date] testcommit3174 -> origin/testcommit3174
2420 = [up to date] testcommit3175 -> origin/testcommit3175
2421 = [up to date] testcommit3176 -> origin/testcommit3176
2422 = [up to date] testcommit3177 -> origin/testcommit3177
2423 = [up to date] testcommit3178 -> origin/testcommit3178
2424 = [up to date] testcommit3179 -> origin/testcommit3179
2425 = [up to date] testcommit318 -> origin/testcommit318
2426 = [up to date] testcommit3180 -> origin/testcommit3180
2427 = [up to date] testcommit3181 -> origin/testcommit3181
2428 = [up to date] testcommit3182 -> origin/testcommit3182
2429 = [up to date] testcommit3183 -> origin/testcommit3183
2430 = [up to date] testcommit3184 -> origin/testcommit3184
2431 = [up to date] testcommit3185 -> origin/testcommit3185
2432 = [up to date] testcommit3186 -> origin/testcommit3186
2433 = [up to date] testcommit3187 -> origin/testcommit3187
2434 = [up to date] testcommit3188 -> origin/testcommit3188
2435 = [up to date] testcommit3189 -> origin/testcommit3189
2436 = [up to date] testcommit319 -> origin/testcommit319
2437 = [up to date] testcommit3190 -> origin/testcommit3190
2438 = [up to date] testcommit3191 -> origin/testcommit3191
2439 = [up to date] testcommit3192 -> origin/testcommit3192
2440 = [up to date] testcommit3193 -> origin/testcommit3193
2441 = [up to date] testcommit3194 -> origin/testcommit3194
2442 = [up to date] testcommit3195 -> origin/testcommit3195
2443 = [up to date] testcommit3196 -> origin/testcommit3196
2444 = [up to date] testcommit3197 -> origin/testcommit3197
2445 = [up to date] testcommit3198 -> origin/testcommit3198
2446 = [up to date] testcommit3199 -> origin/testcommit3199
2447 = [up to date] testcommit32 -> origin/testcommit32
2448 = [up to date] testcommit320 -> origin/testcommit320
2449 = [up to date] testcommit3200 -> origin/testcommit3200
2450 = [up to date] testcommit3201 -> origin/testcommit3201
2451 = [up to date] testcommit3202 -> origin/testcommit3202
2452 = [up to date] testcommit3203 -> origin/testcommit3203
2453 = [up to date] testcommit3204 -> origin/testcommit3204
2454 = [up to date] testcommit3205 -> origin/testcommit3205
2455 = [up to date] testcommit3206 -> origin/testcommit3206
2456 = [up to date] testcommit3207 -> origin/testcommit3207
2457 = [up to date] testcommit3208 -> origin/testcommit3208
2458 = [up to date] testcommit3209 -> origin/testcommit3209
2459 = [up to date] testcommit321 -> origin/testcommit321
2460 = [up to date] testcommit3210 -> origin/testcommit3210
2461 = [up to date] testcommit3211 -> origin/testcommit3211
2462 = [up to date] testcommit3212 -> origin/testcommit3212
2463 = [up to date] testcommit3213 -> origin/testcommit3213
2464 = [up to date] testcommit3214 -> origin/testcommit3214
2465 = [up to date] testcommit3215 -> origin/testcommit3215
2466 = [up to date] testcommit3216 -> origin/testcommit3216
2467 = [up to date] testcommit3217 -> origin/testcommit3217
2468 = [up to date] testcommit3218 -> origin/testcommit3218
2469 = [up to date] testcommit3219 -> origin/testcommit3219
2470 = [up to date] testcommit322 -> origin/testcommit322
2471 = [up to date] testcommit3220 -> origin/testcommit3220
2472 = [up to date] testcommit3221 -> origin/testcommit3221
2473 = [up to date] testcommit3222 -> origin/testcommit3222
2474 = [up to date] testcommit3223 -> origin/testcommit3223
2475 = [up to date] testcommit3224 -> origin/testcommit3224
2476 = [up to date] testcommit3225 -> origin/testcommit3225
2477 = [up to date] testcommit3226 -> origin/testcommit3226
2478 = [up to date] testcommit3227 -> origin/testcommit3227
2479 = [up to date] testcommit3228 -> origin/testcommit3228
2480 = [up to date] testcommit3229 -> origin/testcommit3229
2481 = [up to date] testcommit323 -> origin/testcommit323
2482 = [up to date] testcommit3230 -> origin/testcommit3230
2483 = [up to date] testcommit3231 -> origin/testcommit3231
2484 = [up to date] testcommit3232 -> origin/testcommit3232
2485 = [up to date] testcommit3233 -> origin/testcommit3233
2486 = [up to date] testcommit3234 -> origin/testcommit3234
2487 = [up to date] testcommit3235 -> origin/testcommit3235
2488 = [up to date] testcommit3236 -> origin/testcommit3236
2489 = [up to date] testcommit3237 -> origin/testcommit3237
2490 = [up to date] testcommit3238 -> origin/testcommit3238
2491 = [up to date] testcommit3239 -> origin/testcommit3239
2492 = [up to date] testcommit324 -> origin/testcommit324
2493 = [up to date] testcommit3240 -> origin/testcommit3240
2494 = [up to date] testcommit3241 -> origin/testcommit3241
2495 = [up to date] testcommit3242 -> origin/testcommit3242
2496 = [up to date] testcommit3243 -> origin/testcommit3243
2497 = [up to date] testcommit3244 -> origin/testcommit3244
2498 = [up to date] testcommit3245 -> origin/testcommit3245
2499 = [up to date] testcommit3246 -> origin/testcommit3246
2500 = [up to date] testcommit3247 -> origin/testcommit3247
2501 = [up to date] testcommit3248 -> origin/testcommit3248
2502 = [up to date] testcommit3249 -> origin/testcommit3249
2503 = [up to date] testcommit325 -> origin/testcommit325
2504 = [up to date] testcommit3250 -> origin/testcommit3250
2505 = [up to date] testcommit3251 -> origin/testcommit3251
2506 = [up to date] testcommit3252 -> origin/testcommit3252
2507 = [up to date] testcommit3253 -> origin/testcommit3253
2508 = [up to date] testcommit3254 -> origin/testcommit3254
2509 = [up to date] testcommit3255 -> origin/testcommit3255
2510 = [up to date] testcommit3256 -> origin/testcommit3256
2511 = [up to date] testcommit3257 -> origin/testcommit3257
2512 = [up to date] testcommit3258 -> origin/testcommit3258
2513 = [up to date] testcommit3259 -> origin/testcommit3259
2514 = [up to date] testcommit326 -> origin/testcommit326
2515 = [up to date] testcommit3260 -> origin/testcommit3260
2516 = [up to date] testcommit3261 -> origin/testcommit3261
2517 = [up to date] testcommit3262 -> origin/testcommit3262
2518 = [up to date] testcommit3263 -> origin/testcommit3263
2519 = [up to date] testcommit3264 -> origin/testcommit3264
2520 = [up to date] testcommit3265 -> origin/testcommit3265
2521 = [up to date] testcommit3266 -> origin/testcommit3266
2522 = [up to date] testcommit3267 -> origin/testcommit3267
2523 = [up to date] testcommit3268 -> origin/testcommit3268
2524 = [up to date] testcommit3269 -> origin/testcommit3269
2525 = [up to date] testcommit327 -> origin/testcommit327
2526 = [up to date] testcommit3270 -> origin/testcommit3270
2527 = [up to date] testcommit3271 -> origin/testcommit3271
2528 = [up to date] testcommit3272 -> origin/testcommit3272
2529 = [up to date] testcommit3273 -> origin/testcommit3273
2530 = [up to date] testcommit3274 -> origin/testcommit3274
2531 = [up to date] testcommit3275 -> origin/testcommit3275
2532 = [up to date] testcommit3276 -> origin/testcommit3276
2533 = [up to date] testcommit3277 -> origin/testcommit3277
2534 = [up to date] testcommit3278 -> origin/testcommit3278
2535 = [up to date] testcommit3279 -> origin/testcommit3279
2536 = [up to date] testcommit328 -> origin/testcommit328
2537 = [up to date] testcommit3280 -> origin/testcommit3280
2538 = [up to date] testcommit3281 -> origin/testcommit3281
2539 = [up to date] testcommit3282 -> origin/testcommit3282
2540 = [up to date] testcommit3283 -> origin/testcommit3283
2541 = [up to date] testcommit3284 -> origin/testcommit3284
2542 = [up to date] testcommit3285 -> origin/testcommit3285
2543 = [up to date] testcommit3286 -> origin/testcommit3286
2544 = [up to date] testcommit3287 -> origin/testcommit3287
2545 = [up to date] testcommit3288 -> origin/testcommit3288
2546 = [up to date] testcommit3289 -> origin/testcommit3289
2547 = [up to date] testcommit329 -> origin/testcommit329
2548 = [up to date] testcommit3290 -> origin/testcommit3290
2549 = [up to date] testcommit3291 -> origin/testcommit3291
2550 = [up to date] testcommit3292 -> origin/testcommit3292
2551 = [up to date] testcommit3293 -> origin/testcommit3293
2552 = [up to date] testcommit3294 -> origin/testcommit3294
2553 = [up to date] testcommit3295 -> origin/testcommit3295
2554 = [up to date] testcommit3296 -> origin/testcommit3296
2555 = [up to date] testcommit3297 -> origin/testcommit3297
2556 = [up to date] testcommit3298 -> origin/testcommit3298
2557 = [up to date] testcommit3299 -> origin/testcommit3299
2558 = [up to date] testcommit33 -> origin/testcommit33
2559 = [up to date] testcommit330 -> origin/testcommit330
2560 = [up to date] testcommit3300 -> origin/testcommit3300
2561 = [up to date] testcommit3301 -> origin/testcommit3301
2562 = [up to date] testcommit3302 -> origin/testcommit3302
2563 = [up to date] testcommit3303 -> origin/testcommit3303
2564 = [up to date] testcommit3304 -> origin/testcommit3304
2565 = [up to date] testcommit3305 -> origin/testcommit3305
2566 = [up to date] testcommit3306 -> origin/testcommit3306
2567 = [up to date] testcommit3307 -> origin/testcommit3307
2568 = [up to date] testcommit3308 -> origin/testcommit3308
2569 = [up to date] testcommit3309 -> origin/testcommit3309
2570 = [up to date] testcommit331 -> origin/testcommit331
2571 = [up to date] testcommit3310 -> origin/testcommit3310
2572 = [up to date] testcommit3311 -> origin/testcommit3311
2573 = [up to date] testcommit3312 -> origin/testcommit3312
2574 = [up to date] testcommit3313 -> origin/testcommit3313
2575 = [up to date] testcommit3314 -> origin/testcommit3314
2576 = [up to date] testcommit3315 -> origin/testcommit3315
2577 = [up to date] testcommit3316 -> origin/testcommit3316
2578 = [up to date] testcommit3317 -> origin/testcommit3317
2579 = [up to date] testcommit3318 -> origin/testcommit3318
2580 = [up to date] testcommit3319 -> origin/testcommit3319
2581 = [up to date] testcommit332 -> origin/testcommit332
2582 = [up to date] testcommit3320 -> origin/testcommit3320
2583 = [up to date] testcommit3321 -> origin/testcommit3321
2584 = [up to date] testcommit3322 -> origin/testcommit3322
2585 = [up to date] testcommit3323 -> origin/testcommit3323
2586 = [up to date] testcommit3324 -> origin/testcommit3324
2587 = [up to date] testcommit3325 -> origin/testcommit3325
2588 = [up to date] testcommit3326 -> origin/testcommit3326
2589 = [up to date] testcommit3327 -> origin/testcommit3327
2590 = [up to date] testcommit3328 -> origin/testcommit3328
2591 = [up to date] testcommit3329 -> origin/testcommit3329
2592 = [up to date] testcommit333 -> origin/testcommit333
2593 = [up to date] testcommit3330 -> origin/testcommit3330
2594 = [up to date] testcommit3331 -> origin/testcommit3331
2595 = [up to date] testcommit3332 -> origin/testcommit3332
2596 = [up to date] testcommit3333 -> origin/testcommit3333
2597 = [up to date] testcommit3334 -> origin/testcommit3334
2598 = [up to date] testcommit3335 -> origin/testcommit3335
2599 = [up to date] testcommit3336 -> origin/testcommit3336
2600 = [up to date] testcommit3337 -> origin/testcommit3337
2601 = [up to date] testcommit3338 -> origin/testcommit3338
2602 = [up to date] testcommit3339 -> origin/testcommit3339
2603 = [up to date] testcommit334 -> origin/testcommit334
2604 = [up to date] testcommit3340 -> origin/testcommit3340
2605 = [up to date] testcommit3341 -> origin/testcommit3341
2606 = [up to date] testcommit3342 -> origin/testcommit3342
2607 = [up to date] testcommit3343 -> origin/testcommit3343
2608 = [up to date] testcommit3344 -> origin/testcommit3344
2609 = [up to date] testcommit3345 -> origin/testcommit3345
2610 = [up to date] testcommit3346 -> origin/testcommit3346
2611 = [up to date] testcommit3347 -> origin/testcommit3347
2612 = [up to date] testcommit3348 -> origin/testcommit3348
2613 = [up to date] testcommit3349 -> origin/testcommit3349
2614 = [up to date] testcommit335 -> origin/testcommit335
2615 = [up to date] testcommit3350 -> origin/testcommit3350
2616 = [up to date] testcommit3351 -> origin/testcommit3351
2617 = [up to date] testcommit3352 -> origin/testcommit3352
2618 = [up to date] testcommit3353 -> origin/testcommit3353
2619 = [up to date] testcommit3354 -> origin/testcommit3354
2620 = [up to date] testcommit3355 -> origin/testcommit3355
2621 = [up to date] testcommit3356 -> origin/testcommit3356
2622 = [up to date] testcommit3357 -> origin/testcommit3357
2623 = [up to date] testcommit3358 -> origin/testcommit3358
2624 = [up to date] testcommit3359 -> origin/testcommit3359
2625 = [up to date] testcommit336 -> origin/testcommit336
2626 = [up to date] testcommit3360 -> origin/testcommit3360
2627 = [up to date] testcommit3361 -> origin/testcommit3361
2628 = [up to date] testcommit3362 -> origin/testcommit3362
2629 = [up to date] testcommit3363 -> origin/testcommit3363
2630 = [up to date] testcommit3364 -> origin/testcommit3364
2631 = [up to date] testcommit3365 -> origin/testcommit3365
2632 = [up to date] testcommit3366 -> origin/testcommit3366
2633 = [up to date] testcommit3367 -> origin/testcommit3367
2634 = [up to date] testcommit3368 -> origin/testcommit3368
2635 = [up to date] testcommit3369 -> origin/testcommit3369
2636 = [up to date] testcommit337 -> origin/testcommit337
2637 = [up to date] testcommit3370 -> origin/testcommit3370
2638 = [up to date] testcommit3371 -> origin/testcommit3371
2639 = [up to date] testcommit3372 -> origin/testcommit3372
2640 = [up to date] testcommit3373 -> origin/testcommit3373
2641 = [up to date] testcommit3374 -> origin/testcommit3374
2642 = [up to date] testcommit3375 -> origin/testcommit3375
2643 = [up to date] testcommit3376 -> origin/testcommit3376
2644 = [up to date] testcommit3377 -> origin/testcommit3377
2645 = [up to date] testcommit3378 -> origin/testcommit3378
2646 = [up to date] testcommit3379 -> origin/testcommit3379
2647 = [up to date] testcommit338 -> origin/testcommit338
2648 = [up to date] testcommit3380 -> origin/testcommit3380
2649 = [up to date] testcommit3381 -> origin/testcommit3381
2650 = [up to date] testcommit3382 -> origin/testcommit3382
2651 = [up to date] testcommit3383 -> origin/testcommit3383
2652 = [up to date] testcommit3384 -> origin/testcommit3384
2653 = [up to date] testcommit3385 -> origin/testcommit3385
2654 = [up to date] testcommit3386 -> origin/testcommit3386
2655 = [up to date] testcommit3387 -> origin/testcommit3387
2656 = [up to date] testcommit3388 -> origin/testcommit3388
2657 = [up to date] testcommit3389 -> origin/testcommit3389
2658 = [up to date] testcommit339 -> origin/testcommit339
2659 = [up to date] testcommit3390 -> origin/testcommit3390
2660 = [up to date] testcommit3391 -> origin/testcommit3391
2661 = [up to date] testcommit3392 -> origin/testcommit3392
2662 = [up to date] testcommit3393 -> origin/testcommit3393
2663 = [up to date] testcommit3394 -> origin/testcommit3394
2664 = [up to date] testcommit3395 -> origin/testcommit3395
2665 = [up to date] testcommit3396 -> origin/testcommit3396
2666 = [up to date] testcommit3397 -> origin/testcommit3397
2667 = [up to date] testcommit3398 -> origin/testcommit3398
2668 = [up to date] testcommit3399 -> origin/testcommit3399
2669 = [up to date] testcommit34 -> origin/testcommit34
2670 = [up to date] testcommit340 -> origin/testcommit340
2671 = [up to date] testcommit3400 -> origin/testcommit3400
2672 = [up to date] testcommit3401 -> origin/testcommit3401
2673 = [up to date] testcommit3402 -> origin/testcommit3402
2674 = [up to date] testcommit3403 -> origin/testcommit3403
2675 = [up to date] testcommit3404 -> origin/testcommit3404
2676 = [up to date] testcommit3405 -> origin/testcommit3405
2677 = [up to date] testcommit3406 -> origin/testcommit3406
2678 = [up to date] testcommit3407 -> origin/testcommit3407
2679 = [up to date] testcommit3408 -> origin/testcommit3408
2680 = [up to date] testcommit3409 -> origin/testcommit3409
2681 = [up to date] testcommit341 -> origin/testcommit341
2682 = [up to date] testcommit3410 -> origin/testcommit3410
2683 = [up to date] testcommit3411 -> origin/testcommit3411
2684 = [up to date] testcommit3412 -> origin/testcommit3412
2685 = [up to date] testcommit3413 -> origin/testcommit3413
2686 = [up to date] testcommit3414 -> origin/testcommit3414
2687 = [up to date] testcommit3415 -> origin/testcommit3415
2688 = [up to date] testcommit3416 -> origin/testcommit3416
2689 = [up to date] testcommit3417 -> origin/testcommit3417
2690 = [up to date] testcommit3418 -> origin/testcommit3418
2691 = [up to date] testcommit3419 -> origin/testcommit3419
2692 = [up to date] testcommit342 -> origin/testcommit342
2693 = [up to date] testcommit3420 -> origin/testcommit3420
2694 = [up to date] testcommit3421 -> origin/testcommit3421
2695 = [up to date] testcommit3422 -> origin/testcommit3422
2696 = [up to date] testcommit3423 -> origin/testcommit3423
2697 = [up to date] testcommit3424 -> origin/testcommit3424
2698 = [up to date] testcommit3425 -> origin/testcommit3425
2699 = [up to date] testcommit3426 -> origin/testcommit3426
2700 = [up to date] testcommit3427 -> origin/testcommit3427
2701 = [up to date] testcommit3428 -> origin/testcommit3428
2702 = [up to date] testcommit3429 -> origin/testcommit3429
2703 = [up to date] testcommit343 -> origin/testcommit343
2704 = [up to date] testcommit3430 -> origin/testcommit3430
2705 = [up to date] testcommit3431 -> origin/testcommit3431
2706 = [up to date] testcommit3432 -> origin/testcommit3432
2707 = [up to date] testcommit3433 -> origin/testcommit3433
2708 = [up to date] testcommit3434 -> origin/testcommit3434
2709 = [up to date] testcommit3435 -> origin/testcommit3435
2710 = [up to date] testcommit3436 -> origin/testcommit3436
2711 = [up to date] testcommit3437 -> origin/testcommit3437
2712 = [up to date] testcommit3438 -> origin/testcommit3438
2713 = [up to date] testcommit3439 -> origin/testcommit3439
2714 = [up to date] testcommit344 -> origin/testcommit344
2715 = [up to date] testcommit3440 -> origin/testcommit3440
2716 = [up to date] testcommit3441 -> origin/testcommit3441
2717 = [up to date] testcommit3442 -> origin/testcommit3442
2718 = [up to date] testcommit3443 -> origin/testcommit3443
2719 = [up to date] testcommit3444 -> origin/testcommit3444
2720 = [up to date] testcommit3445 -> origin/testcommit3445
2721 = [up to date] testcommit3446 -> origin/testcommit3446
2722 = [up to date] testcommit3447 -> origin/testcommit3447
2723 = [up to date] testcommit3448 -> origin/testcommit3448
2724 = [up to date] testcommit3449 -> origin/testcommit3449
2725 = [up to date] testcommit345 -> origin/testcommit345
2726 = [up to date] testcommit3450 -> origin/testcommit3450
2727 = [up to date] testcommit3451 -> origin/testcommit3451
2728 = [up to date] testcommit3452 -> origin/testcommit3452
2729 = [up to date] testcommit3453 -> origin/testcommit3453
2730 = [up to date] testcommit3454 -> origin/testcommit3454
2731 = [up to date] testcommit3455 -> origin/testcommit3455
2732 = [up to date] testcommit3456 -> origin/testcommit3456
2733 = [up to date] testcommit3457 -> origin/testcommit3457
2734 = [up to date] testcommit3458 -> origin/testcommit3458
2735 = [up to date] testcommit3459 -> origin/testcommit3459
2736 = [up to date] testcommit346 -> origin/testcommit346
2737 = [up to date] testcommit3460 -> origin/testcommit3460
2738 = [up to date] testcommit3461 -> origin/testcommit3461
2739 = [up to date] testcommit3462 -> origin/testcommit3462
2740 = [up to date] testcommit3463 -> origin/testcommit3463
2741 = [up to date] testcommit3464 -> origin/testcommit3464
2742 = [up to date] testcommit3465 -> origin/testcommit3465
2743 = [up to date] testcommit3466 -> origin/testcommit3466
2744 = [up to date] testcommit3467 -> origin/testcommit3467
2745 = [up to date] testcommit3468 -> origin/testcommit3468
2746 = [up to date] testcommit3469 -> origin/testcommit3469
2747 = [up to date] testcommit347 -> origin/testcommit347
2748 = [up to date] testcommit3470 -> origin/testcommit3470
2749 = [up to date] testcommit3471 -> origin/testcommit3471
2750 = [up to date] testcommit3472 -> origin/testcommit3472
2751 = [up to date] testcommit3473 -> origin/testcommit3473
2752 = [up to date] testcommit3474 -> origin/testcommit3474
2753 = [up to date] testcommit3475 -> origin/testcommit3475
2754 = [up to date] testcommit3476 -> origin/testcommit3476
2755 = [up to date] testcommit3477 -> origin/testcommit3477
2756 = [up to date] testcommit3478 -> origin/testcommit3478
2757 = [up to date] testcommit3479 -> origin/testcommit3479
2758 = [up to date] testcommit348 -> origin/testcommit348
2759 = [up to date] testcommit3480 -> origin/testcommit3480
2760 = [up to date] testcommit3481 -> origin/testcommit3481
2761 = [up to date] testcommit3482 -> origin/testcommit3482
2762 = [up to date] testcommit3483 -> origin/testcommit3483
2763 = [up to date] testcommit3484 -> origin/testcommit3484
2764 = [up to date] testcommit3485 -> origin/testcommit3485
2765 = [up to date] testcommit3486 -> origin/testcommit3486
2766 = [up to date] testcommit3487 -> origin/testcommit3487
2767 = [up to date] testcommit3488 -> origin/testcommit3488
2768 = [up to date] testcommit3489 -> origin/testcommit3489
2769 = [up to date] testcommit349 -> origin/testcommit349
2770 = [up to date] testcommit3490 -> origin/testcommit3490
2771 = [up to date] testcommit3491 -> origin/testcommit3491
2772 = [up to date] testcommit3492 -> origin/testcommit3492
2773 = [up to date] testcommit3493 -> origin/testcommit3493
2774 = [up to date] testcommit3494 -> origin/testcommit3494
2775 = [up to date] testcommit3495 -> origin/testcommit3495
2776 = [up to date] testcommit3496 -> origin/testcommit3496
2777 = [up to date] testcommit3497 -> origin/testcommit3497
2778 = [up to date] testcommit3498 -> origin/testcommit3498
2779 = [up to date] testcommit3499 -> origin/testcommit3499
2780 = [up to date] testcommit35 -> origin/testcommit35
2781 = [up to date] testcommit350 -> origin/testcommit350
2782 = [up to date] testcommit3500 -> origin/testcommit3500
2783 = [up to date] testcommit3501 -> origin/testcommit3501
2784 = [up to date] testcommit3502 -> origin/testcommit3502
2785 = [up to date] testcommit3503 -> origin/testcommit3503
2786 = [up to date] testcommit3504 -> origin/testcommit3504
2787 = [up to date] testcommit3505 -> origin/testcommit3505
2788 = [up to date] testcommit3506 -> origin/testcommit3506
2789 = [up to date] testcommit3507 -> origin/testcommit3507
2790 = [up to date] testcommit3508 -> origin/testcommit3508
2791 = [up to date] testcommit3509 -> origin/testcommit3509
2792 = [up to date] testcommit351 -> origin/testcommit351
2793 = [up to date] testcommit3510 -> origin/testcommit3510
2794 = [up to date] testcommit3511 -> origin/testcommit3511
2795 = [up to date] testcommit3512 -> origin/testcommit3512
2796 = [up to date] testcommit3513 -> origin/testcommit3513
2797 = [up to date] testcommit3514 -> origin/testcommit3514
2798 = [up to date] testcommit3515 -> origin/testcommit3515
2799 = [up to date] testcommit3516 -> origin/testcommit3516
2800 = [up to date] testcommit3517 -> origin/testcommit3517
2801 = [up to date] testcommit3518 -> origin/testcommit3518
2802 = [up to date] testcommit3519 -> origin/testcommit3519
2803 = [up to date] testcommit352 -> origin/testcommit352
2804 = [up to date] testcommit3520 -> origin/testcommit3520
2805 = [up to date] testcommit3521 -> origin/testcommit3521
2806 = [up to date] testcommit3522 -> origin/testcommit3522
2807 = [up to date] testcommit3523 -> origin/testcommit3523
2808 = [up to date] testcommit3524 -> origin/testcommit3524
2809 = [up to date] testcommit3525 -> origin/testcommit3525
2810 = [up to date] testcommit3526 -> origin/testcommit3526
2811 = [up to date] testcommit3527 -> origin/testcommit3527
2812 = [up to date] testcommit3528 -> origin/testcommit3528
2813 = [up to date] testcommit3529 -> origin/testcommit3529
2814 = [up to date] testcommit353 -> origin/testcommit353
2815 = [up to date] testcommit3530 -> origin/testcommit3530
2816 = [up to date] testcommit3531 -> origin/testcommit3531
2817 = [up to date] testcommit3532 -> origin/testcommit3532
2818 = [up to date] testcommit3533 -> origin/testcommit3533
2819 = [up to date] testcommit3534 -> origin/testcommit3534
2820 = [up to date] testcommit3535 -> origin/testcommit3535
2821 = [up to date] testcommit3536 -> origin/testcommit3536
2822 = [up to date] testcommit3537 -> origin/testcommit3537
2823 = [up to date] testcommit3538 -> origin/testcommit3538
2824 = [up to date] testcommit3539 -> origin/testcommit3539
2825 = [up to date] testcommit354 -> origin/testcommit354
2826 = [up to date] testcommit3540 -> origin/testcommit3540
2827 = [up to date] testcommit3541 -> origin/testcommit3541
2828 = [up to date] testcommit3542 -> origin/testcommit3542
2829 = [up to date] testcommit3543 -> origin/testcommit3543
2830 = [up to date] testcommit3544 -> origin/testcommit3544
2831 = [up to date] testcommit3545 -> origin/testcommit3545
2832 = [up to date] testcommit3546 -> origin/testcommit3546
2833 = [up to date] testcommit3547 -> origin/testcommit3547
2834 = [up to date] testcommit3548 -> origin/testcommit3548
2835 = [up to date] testcommit3549 -> origin/testcommit3549
2836 = [up to date] testcommit355 -> origin/testcommit355
2837 = [up to date] testcommit3550 -> origin/testcommit3550
2838 = [up to date] testcommit3551 -> origin/testcommit3551
2839 = [up to date] testcommit3552 -> origin/testcommit3552
2840 = [up to date] testcommit3553 -> origin/testcommit3553
2841 = [up to date] testcommit3554 -> origin/testcommit3554
2842 = [up to date] testcommit3555 -> origin/testcommit3555
2843 = [up to date] testcommit3556 -> origin/testcommit3556
2844 = [up to date] testcommit3557 -> origin/testcommit3557
2845 = [up to date] testcommit3558 -> origin/testcommit3558
2846 = [up to date] testcommit3559 -> origin/testcommit3559
2847 = [up to date] testcommit356 -> origin/testcommit356
2848 = [up to date] testcommit3560 -> origin/testcommit3560
2849 = [up to date] testcommit3561 -> origin/testcommit3561
2850 = [up to date] testcommit3562 -> origin/testcommit3562
2851 = [up to date] testcommit3563 -> origin/testcommit3563
2852 = [up to date] testcommit3564 -> origin/testcommit3564
2853 = [up to date] testcommit3565 -> origin/testcommit3565
2854 = [up to date] testcommit3566 -> origin/testcommit3566
2855 = [up to date] testcommit3567 -> origin/testcommit3567
2856 = [up to date] testcommit3568 -> origin/testcommit3568
2857 = [up to date] testcommit3569 -> origin/testcommit3569
2858 = [up to date] testcommit357 -> origin/testcommit357
2859 = [up to date] testcommit3570 -> origin/testcommit3570
2860 = [up to date] testcommit3571 -> origin/testcommit3571
2861 = [up to date] testcommit3572 -> origin/testcommit3572
2862 = [up to date] testcommit3573 -> origin/testcommit3573
2863 = [up to date] testcommit3574 -> origin/testcommit3574
2864 = [up to date] testcommit3575 -> origin/testcommit3575
2865 = [up to date] testcommit3576 -> origin/testcommit3576
2866 = [up to date] testcommit3577 -> origin/testcommit3577
2867 = [up to date] testcommit3578 -> origin/testcommit3578
2868 = [up to date] testcommit3579 -> origin/testcommit3579
2869 = [up to date] testcommit358 -> origin/testcommit358
2870 = [up to date] testcommit3580 -> origin/testcommit3580
2871 = [up to date] testcommit3581 -> origin/testcommit3581
2872 = [up to date] testcommit3582 -> origin/testcommit3582
2873 = [up to date] testcommit3583 -> origin/testcommit3583
2874 = [up to date] testcommit3584 -> origin/testcommit3584
2875 = [up to date] testcommit3585 -> origin/testcommit3585
2876 = [up to date] testcommit3586 -> origin/testcommit3586
2877 = [up to date] testcommit3587 -> origin/testcommit3587
2878 = [up to date] testcommit3588 -> origin/testcommit3588
2879 = [up to date] testcommit3589 -> origin/testcommit3589
2880 = [up to date] testcommit359 -> origin/testcommit359
2881 = [up to date] testcommit3590 -> origin/testcommit3590
2882 = [up to date] testcommit3591 -> origin/testcommit3591
2883 = [up to date] testcommit3592 -> origin/testcommit3592
2884 = [up to date] testcommit3593 -> origin/testcommit3593
2885 = [up to date] testcommit3594 -> origin/testcommit3594
2886 = [up to date] testcommit3595 -> origin/testcommit3595
2887 = [up to date] testcommit3596 -> origin/testcommit3596
2888 = [up to date] testcommit3597 -> origin/testcommit3597
2889 = [up to date] testcommit3598 -> origin/testcommit3598
2890 = [up to date] testcommit3599 -> origin/testcommit3599
2891 = [up to date] testcommit36 -> origin/testcommit36
2892 = [up to date] testcommit360 -> origin/testcommit360
2893 = [up to date] testcommit3600 -> origin/testcommit3600
2894 = [up to date] testcommit3601 -> origin/testcommit3601
2895 = [up to date] testcommit3602 -> origin/testcommit3602
2896 = [up to date] testcommit3603 -> origin/testcommit3603
2897 = [up to date] testcommit3604 -> origin/testcommit3604
2898 = [up to date] testcommit3605 -> origin/testcommit3605
2899 = [up to date] testcommit3606 -> origin/testcommit3606
2900 = [up to date] testcommit3607 -> origin/testcommit3607
2901 = [up to date] testcommit3608 -> origin/testcommit3608
2902 = [up to date] testcommit3609 -> origin/testcommit3609
2903 = [up to date] testcommit361 -> origin/testcommit361
2904 = [up to date] testcommit3610 -> origin/testcommit3610
2905 = [up to date] testcommit3611 -> origin/testcommit3611
2906 = [up to date] testcommit3612 -> origin/testcommit3612
2907 = [up to date] testcommit3613 -> origin/testcommit3613
2908 = [up to date] testcommit3614 -> origin/testcommit3614
2909 = [up to date] testcommit3615 -> origin/testcommit3615
2910 = [up to date] testcommit3616 -> origin/testcommit3616
2911 = [up to date] testcommit3617 -> origin/testcommit3617
2912 = [up to date] testcommit3618 -> origin/testcommit3618
2913 = [up to date] testcommit3619 -> origin/testcommit3619
2914 = [up to date] testcommit362 -> origin/testcommit362
2915 = [up to date] testcommit3620 -> origin/testcommit3620
2916 = [up to date] testcommit3621 -> origin/testcommit3621
2917 = [up to date] testcommit3622 -> origin/testcommit3622
2918 = [up to date] testcommit3623 -> origin/testcommit3623
2919 = [up to date] testcommit3624 -> origin/testcommit3624
2920 = [up to date] testcommit3625 -> origin/testcommit3625
2921 = [up to date] testcommit3626 -> origin/testcommit3626
2922 = [up to date] testcommit3627 -> origin/testcommit3627
2923 = [up to date] testcommit3628 -> origin/testcommit3628
2924 = [up to date] testcommit3629 -> origin/testcommit3629
2925 = [up to date] testcommit363 -> origin/testcommit363
2926 = [up to date] testcommit3630 -> origin/testcommit3630
2927 = [up to date] testcommit3631 -> origin/testcommit3631
2928 = [up to date] testcommit3632 -> origin/testcommit3632
2929 = [up to date] testcommit3633 -> origin/testcommit3633
2930 = [up to date] testcommit3634 -> origin/testcommit3634
2931 = [up to date] testcommit3635 -> origin/testcommit3635
2932 = [up to date] testcommit3636 -> origin/testcommit3636
2933 = [up to date] testcommit3637 -> origin/testcommit3637
2934 = [up to date] testcommit3638 -> origin/testcommit3638
2935 = [up to date] testcommit3639 -> origin/testcommit3639
2936 = [up to date] testcommit364 -> origin/testcommit364
2937 = [up to date] testcommit3640 -> origin/testcommit3640
2938 = [up to date] testcommit3641 -> origin/testcommit3641
2939 = [up to date] testcommit3642 -> origin/testcommit3642
2940 = [up to date] testcommit3643 -> origin/testcommit3643
2941 = [up to date] testcommit3644 -> origin/testcommit3644
2942 = [up to date] testcommit3645 -> origin/testcommit3645
2943 = [up to date] testcommit3646 -> origin/testcommit3646
2944 = [up to date] testcommit3647 -> origin/testcommit3647
2945 = [up to date] testcommit3648 -> origin/testcommit3648
2946 = [up to date] testcommit3649 -> origin/testcommit3649
2947 = [up to date] testcommit365 -> origin/testcommit365
2948 = [up to date] testcommit3650 -> origin/testcommit3650
2949 = [up to date] testcommit3651 -> origin/testcommit3651
2950 = [up to date] testcommit3652 -> origin/testcommit3652
2951 = [up to date] testcommit3653 -> origin/testcommit3653
2952 = [up to date] testcommit3654 -> origin/testcommit3654
2953 = [up to date] testcommit3655 -> origin/testcommit3655
2954 = [up to date] testcommit3656 -> origin/testcommit3656
2955 = [up to date] testcommit3657 -> origin/testcommit3657
2956 = [up to date] testcommit3658 -> origin/testcommit3658
2957 = [up to date] testcommit3659 -> origin/testcommit3659
2958 = [up to date] testcommit366 -> origin/testcommit366
2959 = [up to date] testcommit3660 -> origin/testcommit3660
2960 = [up to date] testcommit3661 -> origin/testcommit3661
2961 = [up to date] testcommit3662 -> origin/testcommit3662
2962 = [up to date] testcommit3663 -> origin/testcommit3663
2963 = [up to date] testcommit3664 -> origin/testcommit3664
2964 = [up to date] testcommit3665 -> origin/testcommit3665
2965 = [up to date] testcommit3666 -> origin/testcommit3666
2966 = [up to date] testcommit3667 -> origin/testcommit3667
2967 = [up to date] testcommit3668 -> origin/testcommit3668
2968 = [up to date] testcommit3669 -> origin/testcommit3669
2969 = [up to date] testcommit367 -> origin/testcommit367
2970 = [up to date] testcommit3670 -> origin/testcommit3670
2971 = [up to date] testcommit3671 -> origin/testcommit3671
2972 = [up to date] testcommit3672 -> origin/testcommit3672
2973 = [up to date] testcommit3673 -> origin/testcommit3673
2974 = [up to date] testcommit3674 -> origin/testcommit3674
2975 = [up to date] testcommit3675 -> origin/testcommit3675
2976 = [up to date] testcommit3676 -> origin/testcommit3676
2977 = [up to date] testcommit3677 -> origin/testcommit3677
2978 = [up to date] testcommit3678 -> origin/testcommit3678
2979 = [up to date] testcommit3679 -> origin/testcommit3679
2980 = [up to date] testcommit368 -> origin/testcommit368
2981 = [up to date] testcommit3680 -> origin/testcommit3680
2982 = [up to date] testcommit3681 -> origin/testcommit3681
2983 = [up to date] testcommit3682 -> origin/testcommit3682
2984 = [up to date] testcommit3683 -> origin/testcommit3683
2985 = [up to date] testcommit3684 -> origin/testcommit3684
2986 = [up to date] testcommit3685 -> origin/testcommit3685
2987 = [up to date] testcommit3686 -> origin/testcommit3686
2988 = [up to date] testcommit3687 -> origin/testcommit3687
2989 = [up to date] testcommit3688 -> origin/testcommit3688
2990 = [up to date] testcommit3689 -> origin/testcommit3689
2991 = [up to date] testcommit369 -> origin/testcommit369
2992 = [up to date] testcommit3690 -> origin/testcommit3690
2993 = [up to date] testcommit3691 -> origin/testcommit3691
2994 = [up to date] testcommit3692 -> origin/testcommit3692
2995 = [up to date] testcommit3693 -> origin/testcommit3693
2996 = [up to date] testcommit3694 -> origin/testcommit3694
2997 = [up to date] testcommit3695 -> origin/testcommit3695
2998 = [up to date] testcommit3696 -> origin/testcommit3696
2999 = [up to date] testcommit3697 -> origin/testcommit3697
3000 = [up to date] testcommit3698 -> origin/testcommit3698
3001 = [up to date] testcommit3699 -> origin/testcommit3699
3002 = [up to date] testcommit37 -> origin/testcommit37
3003 = [up to date] testcommit370 -> origin/testcommit370
3004 = [up to date] testcommit3700 -> origin/testcommit3700
3005 = [up to date] testcommit3701 -> origin/testcommit3701
3006 = [up to date] testcommit3702 -> origin/testcommit3702
3007 = [up to date] testcommit3703 -> origin/testcommit3703
3008 = [up to date] testcommit3704 -> origin/testcommit3704
3009 = [up to date] testcommit3705 -> origin/testcommit3705
3010 = [up to date] testcommit3706 -> origin/testcommit3706
3011 = [up to date] testcommit3707 -> origin/testcommit3707
3012 = [up to date] testcommit3708 -> origin/testcommit3708
3013 = [up to date] testcommit3709 -> origin/testcommit3709
3014 = [up to date] testcommit371 -> origin/testcommit371
3015 = [up to date] testcommit3710 -> origin/testcommit3710
3016 = [up to date] testcommit3711 -> origin/testcommit3711
3017 = [up to date] testcommit3712 -> origin/testcommit3712
3018 = [up to date] testcommit3713 -> origin/testcommit3713
3019 = [up to date] testcommit3714 -> origin/testcommit3714
3020 = [up to date] testcommit3715 -> origin/testcommit3715
3021 = [up to date] testcommit3716 -> origin/testcommit3716
3022 = [up to date] testcommit3717 -> origin/testcommit3717
3023 = [up to date] testcommit3718 -> origin/testcommit3718
3024 = [up to date] testcommit3719 -> origin/testcommit3719
3025 = [up to date] testcommit372 -> origin/testcommit372
3026 = [up to date] testcommit3720 -> origin/testcommit3720
3027 = [up to date] testcommit3721 -> origin/testcommit3721
3028 = [up to date] testcommit3722 -> origin/testcommit3722
3029 = [up to date] testcommit3723 -> origin/testcommit3723
3030 = [up to date] testcommit3724 -> origin/testcommit3724
3031 = [up to date] testcommit3725 -> origin/testcommit3725
3032 = [up to date] testcommit3726 -> origin/testcommit3726
3033 = [up to date] testcommit3727 -> origin/testcommit3727
3034 = [up to date] testcommit3728 -> origin/testcommit3728
3035 = [up to date] testcommit3729 -> origin/testcommit3729
3036 = [up to date] testcommit373 -> origin/testcommit373
3037 = [up to date] testcommit3730 -> origin/testcommit3730
3038 = [up to date] testcommit3731 -> origin/testcommit3731
3039 = [up to date] testcommit3732 -> origin/testcommit3732
3040 = [up to date] testcommit3733 -> origin/testcommit3733
3041 = [up to date] testcommit3734 -> origin/testcommit3734
3042 = [up to date] testcommit3735 -> origin/testcommit3735
3043 = [up to date] testcommit3736 -> origin/testcommit3736
3044 = [up to date] testcommit3737 -> origin/testcommit3737
3045 = [up to date] testcommit3738 -> origin/testcommit3738
3046 = [up to date] testcommit3739 -> origin/testcommit3739
3047 = [up to date] testcommit374 -> origin/testcommit374
3048 = [up to date] testcommit3740 -> origin/testcommit3740
3049 = [up to date] testcommit3741 -> origin/testcommit3741
3050 = [up to date] testcommit3742 -> origin/testcommit3742
3051 = [up to date] testcommit3743 -> origin/testcommit3743
3052 = [up to date] testcommit3744 -> origin/testcommit3744
3053 = [up to date] testcommit3745 -> origin/testcommit3745
3054 = [up to date] testcommit3746 -> origin/testcommit3746
3055 = [up to date] testcommit3747 -> origin/testcommit3747
3056 = [up to date] testcommit3748 -> origin/testcommit3748
3057 = [up to date] testcommit3749 -> origin/testcommit3749
3058 = [up to date] testcommit375 -> origin/testcommit375
3059 = [up to date] testcommit3750 -> origin/testcommit3750
3060 = [up to date] testcommit3751 -> origin/testcommit3751
3061 = [up to date] testcommit3752 -> origin/testcommit3752
3062 = [up to date] testcommit3753 -> origin/testcommit3753
3063 = [up to date] testcommit3754 -> origin/testcommit3754
3064 = [up to date] testcommit3755 -> origin/testcommit3755
3065 = [up to date] testcommit3756 -> origin/testcommit3756
3066 = [up to date] testcommit3757 -> origin/testcommit3757
3067 = [up to date] testcommit3758 -> origin/testcommit3758
3068 = [up to date] testcommit3759 -> origin/testcommit3759
3069 = [up to date] testcommit376 -> origin/testcommit376
3070 = [up to date] testcommit3760 -> origin/testcommit3760
3071 = [up to date] testcommit3761 -> origin/testcommit3761
3072 = [up to date] testcommit3762 -> origin/testcommit3762
3073 = [up to date] testcommit3763 -> origin/testcommit3763
3074 = [up to date] testcommit3764 -> origin/testcommit3764
3075 = [up to date] testcommit3765 -> origin/testcommit3765
3076 = [up to date] testcommit3766 -> origin/testcommit3766
3077 = [up to date] testcommit3767 -> origin/testcommit3767
3078 = [up to date] testcommit3768 -> origin/testcommit3768
3079 = [up to date] testcommit3769 -> origin/testcommit3769
3080 = [up to date] testcommit377 -> origin/testcommit377
3081 = [up to date] testcommit3770 -> origin/testcommit3770
3082 = [up to date] testcommit3771 -> origin/testcommit3771
3083 = [up to date] testcommit3772 -> origin/testcommit3772
3084 = [up to date] testcommit3773 -> origin/testcommit3773
3085 = [up to date] testcommit3774 -> origin/testcommit3774
3086 = [up to date] testcommit3775 -> origin/testcommit3775
3087 = [up to date] testcommit3776 -> origin/testcommit3776
3088 = [up to date] testcommit3777 -> origin/testcommit3777
3089 = [up to date] testcommit3778 -> origin/testcommit3778
3090 = [up to date] testcommit3779 -> origin/testcommit3779
3091 = [up to date] testcommit378 -> origin/testcommit378
3092 = [up to date] testcommit3780 -> origin/testcommit3780
3093 = [up to date] testcommit3781 -> origin/testcommit3781
3094 = [up to date] testcommit3782 -> origin/testcommit3782
3095 = [up to date] testcommit3783 -> origin/testcommit3783
3096 = [up to date] testcommit3784 -> origin/testcommit3784
3097 = [up to date] testcommit3785 -> origin/testcommit3785
3098 = [up to date] testcommit3786 -> origin/testcommit3786
3099 = [up to date] testcommit3787 -> origin/testcommit3787
3100 = [up to date] testcommit3788 -> origin/testcommit3788
3101 = [up to date] testcommit3789 -> origin/testcommit3789
3102 = [up to date] testcommit379 -> origin/testcommit379
3103 = [up to date] testcommit3790 -> origin/testcommit3790
3104 = [up to date] testcommit3791 -> origin/testcommit3791
3105 = [up to date] testcommit3792 -> origin/testcommit3792
3106 = [up to date] testcommit3793 -> origin/testcommit3793
3107 = [up to date] testcommit3794 -> origin/testcommit3794
3108 = [up to date] testcommit3795 -> origin/testcommit3795
3109 = [up to date] testcommit3796 -> origin/testcommit3796
3110 = [up to date] testcommit3797 -> origin/testcommit3797
3111 = [up to date] testcommit3798 -> origin/testcommit3798
3112 = [up to date] testcommit3799 -> origin/testcommit3799
3113 = [up to date] testcommit38 -> origin/testcommit38
3114 = [up to date] testcommit380 -> origin/testcommit380
3115 = [up to date] testcommit3800 -> origin/testcommit3800
3116 = [up to date] testcommit3801 -> origin/testcommit3801
3117 = [up to date] testcommit3802 -> origin/testcommit3802
3118 = [up to date] testcommit3803 -> origin/testcommit3803
3119 = [up to date] testcommit3804 -> origin/testcommit3804
3120 = [up to date] testcommit3805 -> origin/testcommit3805
3121 = [up to date] testcommit3806 -> origin/testcommit3806
3122 = [up to date] testcommit3807 -> origin/testcommit3807
3123 = [up to date] testcommit3808 -> origin/testcommit3808
3124 = [up to date] testcommit3809 -> origin/testcommit3809
3125 = [up to date] testcommit381 -> origin/testcommit381
3126 = [up to date] testcommit3810 -> origin/testcommit3810
3127 = [up to date] testcommit3811 -> origin/testcommit3811
3128 = [up to date] testcommit3812 -> origin/testcommit3812
3129 = [up to date] testcommit3813 -> origin/testcommit3813
3130 = [up to date] testcommit3814 -> origin/testcommit3814
3131 = [up to date] testcommit3815 -> origin/testcommit3815
3132 = [up to date] testcommit3816 -> origin/testcommit3816
3133 = [up to date] testcommit3817 -> origin/testcommit3817
3134 = [up to date] testcommit3818 -> origin/testcommit3818
3135 = [up to date] testcommit3819 -> origin/testcommit3819
3136 = [up to date] testcommit382 -> origin/testcommit382
3137 = [up to date] testcommit3820 -> origin/testcommit3820
3138 = [up to date] testcommit3821 -> origin/testcommit3821
3139 = [up to date] testcommit3822 -> origin/testcommit3822
3140 = [up to date] testcommit3823 -> origin/testcommit3823
3141 = [up to date] testcommit3824 -> origin/testcommit3824
3142 = [up to date] testcommit3825 -> origin/testcommit3825
3143 = [up to date] testcommit3826 -> origin/testcommit3826
3144 = [up to date] testcommit3827 -> origin/testcommit3827
3145 = [up to date] testcommit3828 -> origin/testcommit3828
3146 = [up to date] testcommit3829 -> origin/testcommit3829
3147 = [up to date] testcommit383 -> origin/testcommit383
3148 = [up to date] testcommit3830 -> origin/testcommit3830
3149 = [up to date] testcommit3831 -> origin/testcommit3831
3150 = [up to date] testcommit3832 -> origin/testcommit3832
3151 = [up to date] testcommit3833 -> origin/testcommit3833
3152 = [up to date] testcommit3834 -> origin/testcommit3834
3153 = [up to date] testcommit3835 -> origin/testcommit3835
3154 = [up to date] testcommit3836 -> origin/testcommit3836
3155 = [up to date] testcommit3837 -> origin/testcommit3837
3156 = [up to date] testcommit3838 -> origin/testcommit3838
3157 = [up to date] testcommit3839 -> origin/testcommit3839
3158 = [up to date] testcommit384 -> origin/testcommit384
3159 = [up to date] testcommit3840 -> origin/testcommit3840
3160 = [up to date] testcommit3841 -> origin/testcommit3841
3161 = [up to date] testcommit3842 -> origin/testcommit3842
3162 = [up to date] testcommit3843 -> origin/testcommit3843
3163 = [up to date] testcommit3844 -> origin/testcommit3844
3164 = [up to date] testcommit3845 -> origin/testcommit3845
3165 = [up to date] testcommit3846 -> origin/testcommit3846
3166 = [up to date] testcommit3847 -> origin/testcommit3847
3167 = [up to date] testcommit3848 -> origin/testcommit3848
3168 = [up to date] testcommit3849 -> origin/testcommit3849
3169 = [up to date] testcommit385 -> origin/testcommit385
3170 = [up to date] testcommit3850 -> origin/testcommit3850
3171 = [up to date] testcommit3851 -> origin/testcommit3851
3172 = [up to date] testcommit3852 -> origin/testcommit3852
3173 = [up to date] testcommit3853 -> origin/testcommit3853
3174 = [up to date] testcommit3854 -> origin/testcommit3854
3175 = [up to date] testcommit3855 -> origin/testcommit3855
3176 = [up to date] testcommit3856 -> origin/testcommit3856
3177 = [up to date] testcommit3857 -> origin/testcommit3857
3178 = [up to date] testcommit3858 -> origin/testcommit3858
3179 = [up to date] testcommit3859 -> origin/testcommit3859
3180 = [up to date] testcommit386 -> origin/testcommit386
3181 = [up to date] testcommit3860 -> origin/testcommit3860
3182 = [up to date] testcommit3861 -> origin/testcommit3861
3183 = [up to date] testcommit3862 -> origin/testcommit3862
3184 = [up to date] testcommit3863 -> origin/testcommit3863
3185 = [up to date] testcommit3864 -> origin/testcommit3864
3186 = [up to date] testcommit3865 -> origin/testcommit3865
3187 = [up to date] testcommit3866 -> origin/testcommit3866
3188 = [up to date] testcommit3867 -> origin/testcommit3867
3189 = [up to date] testcommit3868 -> origin/testcommit3868
3190 = [up to date] testcommit3869 -> origin/testcommit3869
3191 = [up to date] testcommit387 -> origin/testcommit387
3192 = [up to date] testcommit3870 -> origin/testcommit3870
3193 = [up to date] testcommit3871 -> origin/testcommit3871
3194 = [up to date] testcommit3872 -> origin/testcommit3872
3195 = [up to date] testcommit3873 -> origin/testcommit3873
3196 = [up to date] testcommit3874 -> origin/testcommit3874
3197 = [up to date] testcommit3875 -> origin/testcommit3875
3198 = [up to date] testcommit3876 -> origin/testcommit3876
3199 = [up to date] testcommit3877 -> origin/testcommit3877
3200 = [up to date] testcommit3878 -> origin/testcommit3878
3201 = [up to date] testcommit3879 -> origin/testcommit3879
3202 = [up to date] testcommit388 -> origin/testcommit388
3203 = [up to date] testcommit3880 -> origin/testcommit3880
3204 = [up to date] testcommit3881 -> origin/testcommit3881
3205 = [up to date] testcommit3882 -> origin/testcommit3882
3206 = [up to date] testcommit3883 -> origin/testcommit3883
3207 = [up to date] testcommit3884 -> origin/testcommit3884
3208 = [up to date] testcommit3885 -> origin/testcommit3885
3209 = [up to date] testcommit3886 -> origin/testcommit3886
3210 = [up to date] testcommit3887 -> origin/testcommit3887
3211 = [up to date] testcommit3888 -> origin/testcommit3888
3212 = [up to date] testcommit3889 -> origin/testcommit3889
3213 = [up to date] testcommit389 -> origin/testcommit389
3214 = [up to date] testcommit3890 -> origin/testcommit3890
3215 = [up to date] testcommit3891 -> origin/testcommit3891
3216 = [up to date] testcommit3892 -> origin/testcommit3892
3217 = [up to date] testcommit3893 -> origin/testcommit3893
3218 = [up to date] testcommit3894 -> origin/testcommit3894
3219 = [up to date] testcommit3895 -> origin/testcommit3895
3220 = [up to date] testcommit3896 -> origin/testcommit3896
3221 = [up to date] testcommit3897 -> origin/testcommit3897
3222 = [up to date] testcommit3898 -> origin/testcommit3898
3223 = [up to date] testcommit3899 -> origin/testcommit3899
3224 = [up to date] testcommit39 -> origin/testcommit39
3225 = [up to date] testcommit390 -> origin/testcommit390
3226 = [up to date] testcommit3900 -> origin/testcommit3900
3227 = [up to date] testcommit3901 -> origin/testcommit3901
3228 = [up to date] testcommit3902 -> origin/testcommit3902
3229 = [up to date] testcommit3903 -> origin/testcommit3903
3230 = [up to date] testcommit3904 -> origin/testcommit3904
3231 = [up to date] testcommit3905 -> origin/testcommit3905
3232 = [up to date] testcommit3906 -> origin/testcommit3906
3233 = [up to date] testcommit3907 -> origin/testcommit3907
3234 = [up to date] testcommit3908 -> origin/testcommit3908
3235 = [up to date] testcommit3909 -> origin/testcommit3909
3236 = [up to date] testcommit391 -> origin/testcommit391
3237 = [up to date] testcommit3910 -> origin/testcommit3910
3238 = [up to date] testcommit3911 -> origin/testcommit3911
3239 = [up to date] testcommit3912 -> origin/testcommit3912
3240 = [up to date] testcommit3913 -> origin/testcommit3913
3241 = [up to date] testcommit3914 -> origin/testcommit3914
3242 = [up to date] testcommit3915 -> origin/testcommit3915
3243 = [up to date] testcommit3916 -> origin/testcommit3916
3244 = [up to date] testcommit3917 -> origin/testcommit3917
3245 = [up to date] testcommit3918 -> origin/testcommit3918
3246 = [up to date] testcommit3919 -> origin/testcommit3919
3247 = [up to date] testcommit392 -> origin/testcommit392
3248 = [up to date] testcommit3920 -> origin/testcommit3920
3249 = [up to date] testcommit3921 -> origin/testcommit3921
3250 = [up to date] testcommit3922 -> origin/testcommit3922
3251 = [up to date] testcommit3923 -> origin/testcommit3923
3252 = [up to date] testcommit3924 -> origin/testcommit3924
3253 = [up to date] testcommit3925 -> origin/testcommit3925
3254 = [up to date] testcommit3926 -> origin/testcommit3926
3255 = [up to date] testcommit3927 -> origin/testcommit3927
3256 = [up to date] testcommit3928 -> origin/testcommit3928
3257 = [up to date] testcommit3929 -> origin/testcommit3929
3258 = [up to date] testcommit393 -> origin/testcommit393
3259 = [up to date] testcommit3930 -> origin/testcommit3930
3260 = [up to date] testcommit3931 -> origin/testcommit3931
3261 = [up to date] testcommit3932 -> origin/testcommit3932
3262 = [up to date] testcommit3933 -> origin/testcommit3933
3263 = [up to date] testcommit3934 -> origin/testcommit3934
3264 = [up to date] testcommit3935 -> origin/testcommit3935
3265 = [up to date] testcommit3936 -> origin/testcommit3936
3266 = [up to date] testcommit3937 -> origin/testcommit3937
3267 = [up to date] testcommit3938 -> origin/testcommit3938
3268 = [up to date] testcommit3939 -> origin/testcommit3939
3269 = [up to date] testcommit394 -> origin/testcommit394
3270 = [up to date] testcommit3940 -> origin/testcommit3940
3271 = [up to date] testcommit3941 -> origin/testcommit3941
3272 = [up to date] testcommit3942 -> origin/testcommit3942
3273 = [up to date] testcommit3943 -> origin/testcommit3943
3274 = [up to date] testcommit3944 -> origin/testcommit3944
3275 = [up to date] testcommit3945 -> origin/testcommit3945
3276 = [up to date] testcommit3946 -> origin/testcommit3946
3277 = [up to date] testcommit3947 -> origin/testcommit3947
3278 = [up to date] testcommit3948 -> origin/testcommit3948
3279 = [up to date] testcommit3949 -> origin/testcommit3949
3280 = [up to date] testcommit395 -> origin/testcommit395
3281 = [up to date] testcommit3950 -> origin/testcommit3950
3282 = [up to date] testcommit3951 -> origin/testcommit3951
3283 = [up to date] testcommit3952 -> origin/testcommit3952
3284 = [up to date] testcommit3953 -> origin/testcommit3953
3285 = [up to date] testcommit3954 -> origin/testcommit3954
3286 = [up to date] testcommit3955 -> origin/testcommit3955
3287 = [up to date] testcommit3956 -> origin/testcommit3956
3288 = [up to date] testcommit3957 -> origin/testcommit3957
3289 = [up to date] testcommit3958 -> origin/testcommit3958
3290 = [up to date] testcommit3959 -> origin/testcommit3959
3291 = [up to date] testcommit396 -> origin/testcommit396
3292 = [up to date] testcommit3960 -> origin/testcommit3960
3293 = [up to date] testcommit3961 -> origin/testcommit3961
3294 = [up to date] testcommit3962 -> origin/testcommit3962
3295 = [up to date] testcommit3963 -> origin/testcommit3963
3296 = [up to date] testcommit3964 -> origin/testcommit3964
3297 = [up to date] testcommit3965 -> origin/testcommit3965
3298 = [up to date] testcommit3966 -> origin/testcommit3966
3299 = [up to date] testcommit3967 -> origin/testcommit3967
3300 = [up to date] testcommit3968 -> origin/testcommit3968
3301 = [up to date] testcommit3969 -> origin/testcommit3969
3302 = [up to date] testcommit397 -> origin/testcommit397
3303 = [up to date] testcommit3970 -> origin/testcommit3970
3304 = [up to date] testcommit3971 -> origin/testcommit3971
3305 = [up to date] testcommit3972 -> origin/testcommit3972
3306 = [up to date] testcommit3973 -> origin/testcommit3973
3307 = [up to date] testcommit3974 -> origin/testcommit3974
3308 = [up to date] testcommit3975 -> origin/testcommit3975
3309 = [up to date] testcommit3976 -> origin/testcommit3976
3310 = [up to date] testcommit3977 -> origin/testcommit3977
3311 = [up to date] testcommit3978 -> origin/testcommit3978
3312 = [up to date] testcommit3979 -> origin/testcommit3979
3313 = [up to date] testcommit398 -> origin/testcommit398
3314 = [up to date] testcommit3980 -> origin/testcommit3980
3315 = [up to date] testcommit3981 -> origin/testcommit3981
3316 = [up to date] testcommit3982 -> origin/testcommit3982
3317 = [up to date] testcommit3983 -> origin/testcommit3983
3318 = [up to date] testcommit3984 -> origin/testcommit3984
3319 = [up to date] testcommit3985 -> origin/testcommit3985
3320 = [up to date] testcommit3986 -> origin/testcommit3986
3321 = [up to date] testcommit3987 -> origin/testcommit3987
3322 = [up to date] testcommit3988 -> origin/testcommit3988
3323 = [up to date] testcommit3989 -> origin/testcommit3989
3324 = [up to date] testcommit399 -> origin/testcommit399
3325 = [up to date] testcommit3990 -> origin/testcommit3990
3326 = [up to date] testcommit3991 -> origin/testcommit3991
3327 = [up to date] testcommit3992 -> origin/testcommit3992
3328 = [up to date] testcommit3993 -> origin/testcommit3993
3329 = [up to date] testcommit3994 -> origin/testcommit3994
3330 = [up to date] testcommit3995 -> origin/testcommit3995
3331 = [up to date] testcommit3996 -> origin/testcommit3996
3332 = [up to date] testcommit3997 -> origin/testcommit3997
3333 = [up to date] testcommit3998 -> origin/testcommit3998
3334 = [up to date] testcommit3999 -> origin/testcommit3999
3335 = [up to date] testcommit4 -> origin/testcommit4
3336 = [up to date] testcommit40 -> origin/testcommit40
3337 = [up to date] testcommit400 -> origin/testcommit400
3338 = [up to date] testcommit4000 -> origin/testcommit4000
3339 = [up to date] testcommit4001 -> origin/testcommit4001
3340 = [up to date] testcommit4002 -> origin/testcommit4002
3341 = [up to date] testcommit4003 -> origin/testcommit4003
3342 = [up to date] testcommit4004 -> origin/testcommit4004
3343 = [up to date] testcommit4005 -> origin/testcommit4005
3344 = [up to date] testcommit4006 -> origin/testcommit4006
3345 = [up to date] testcommit4007 -> origin/testcommit4007
3346 = [up to date] testcommit4008 -> origin/testcommit4008
3347 = [up to date] testcommit4009 -> origin/testcommit4009
3348 = [up to date] testcommit401 -> origin/testcommit401
3349 = [up to date] testcommit4010 -> origin/testcommit4010
3350 = [up to date] testcommit4011 -> origin/testcommit4011
3351 = [up to date] testcommit4012 -> origin/testcommit4012
3352 = [up to date] testcommit4013 -> origin/testcommit4013
3353 = [up to date] testcommit4014 -> origin/testcommit4014
3354 = [up to date] testcommit4015 -> origin/testcommit4015
3355 = [up to date] testcommit4016 -> origin/testcommit4016
3356 = [up to date] testcommit4017 -> origin/testcommit4017
3357 = [up to date] testcommit4018 -> origin/testcommit4018
3358 = [up to date] testcommit4019 -> origin/testcommit4019
3359 = [up to date] testcommit402 -> origin/testcommit402
3360 = [up to date] testcommit4020 -> origin/testcommit4020
3361 = [up to date] testcommit4021 -> origin/testcommit4021
3362 = [up to date] testcommit4022 -> origin/testcommit4022
3363 = [up to date] testcommit4023 -> origin/testcommit4023
3364 = [up to date] testcommit4024 -> origin/testcommit4024
3365 = [up to date] testcommit4025 -> origin/testcommit4025
3366 = [up to date] testcommit4026 -> origin/testcommit4026
3367 = [up to date] testcommit4027 -> origin/testcommit4027
3368 = [up to date] testcommit4028 -> origin/testcommit4028
3369 = [up to date] testcommit4029 -> origin/testcommit4029
3370 = [up to date] testcommit403 -> origin/testcommit403
3371 = [up to date] testcommit4030 -> origin/testcommit4030
3372 = [up to date] testcommit4031 -> origin/testcommit4031
3373 = [up to date] testcommit4032 -> origin/testcommit4032
3374 = [up to date] testcommit4033 -> origin/testcommit4033
3375 = [up to date] testcommit4034 -> origin/testcommit4034
3376 = [up to date] testcommit4035 -> origin/testcommit4035
3377 = [up to date] testcommit4036 -> origin/testcommit4036
3378 = [up to date] testcommit4037 -> origin/testcommit4037
3379 = [up to date] testcommit4038 -> origin/testcommit4038
3380 = [up to date] testcommit4039 -> origin/testcommit4039
3381 = [up to date] testcommit404 -> origin/testcommit404
3382 = [up to date] testcommit4040 -> origin/testcommit4040
3383 = [up to date] testcommit4041 -> origin/testcommit4041
3384 = [up to date] testcommit4042 -> origin/testcommit4042
3385 = [up to date] testcommit4043 -> origin/testcommit4043
3386 = [up to date] testcommit4044 -> origin/testcommit4044
3387 = [up to date] testcommit4045 -> origin/testcommit4045
3388 = [up to date] testcommit4046 -> origin/testcommit4046
3389 = [up to date] testcommit4047 -> origin/testcommit4047
3390 = [up to date] testcommit4048 -> origin/testcommit4048
3391 = [up to date] testcommit4049 -> origin/testcommit4049
3392 = [up to date] testcommit405 -> origin/testcommit405
3393 = [up to date] testcommit4050 -> origin/testcommit4050
3394 = [up to date] testcommit4051 -> origin/testcommit4051
3395 = [up to date] testcommit4052 -> origin/testcommit4052
3396 = [up to date] testcommit4053 -> origin/testcommit4053
3397 = [up to date] testcommit4054 -> origin/testcommit4054
3398 = [up to date] testcommit4055 -> origin/testcommit4055
3399 = [up to date] testcommit4056 -> origin/testcommit4056
3400 = [up to date] testcommit4057 -> origin/testcommit4057
3401 = [up to date] testcommit4058 -> origin/testcommit4058
3402 = [up to date] testcommit4059 -> origin/testcommit4059
3403 = [up to date] testcommit406 -> origin/testcommit406
3404 = [up to date] testcommit4060 -> origin/testcommit4060
3405 = [up to date] testcommit4061 -> origin/testcommit4061
3406 = [up to date] testcommit4062 -> origin/testcommit4062
3407 = [up to date] testcommit4063 -> origin/testcommit4063
3408 = [up to date] testcommit4064 -> origin/testcommit4064
3409 = [up to date] testcommit4065 -> origin/testcommit4065
3410 = [up to date] testcommit4066 -> origin/testcommit4066
3411 = [up to date] testcommit4067 -> origin/testcommit4067
3412 = [up to date] testcommit4068 -> origin/testcommit4068
3413 = [up to date] testcommit4069 -> origin/testcommit4069
3414 = [up to date] testcommit407 -> origin/testcommit407
3415 = [up to date] testcommit4070 -> origin/testcommit4070
3416 = [up to date] testcommit4071 -> origin/testcommit4071
3417 = [up to date] testcommit4072 -> origin/testcommit4072
3418 = [up to date] testcommit4073 -> origin/testcommit4073
3419 = [up to date] testcommit4074 -> origin/testcommit4074
3420 = [up to date] testcommit4075 -> origin/testcommit4075
3421 = [up to date] testcommit4076 -> origin/testcommit4076
3422 = [up to date] testcommit4077 -> origin/testcommit4077
3423 = [up to date] testcommit4078 -> origin/testcommit4078
3424 = [up to date] testcommit4079 -> origin/testcommit4079
3425 = [up to date] testcommit408 -> origin/testcommit408
3426 = [up to date] testcommit4080 -> origin/testcommit4080
3427 = [up to date] testcommit4081 -> origin/testcommit4081
3428 = [up to date] testcommit4082 -> origin/testcommit4082
3429 = [up to date] testcommit4083 -> origin/testcommit4083
3430 = [up to date] testcommit4084 -> origin/testcommit4084
3431 = [up to date] testcommit4085 -> origin/testcommit4085
3432 = [up to date] testcommit4086 -> origin/testcommit4086
3433 = [up to date] testcommit4087 -> origin/testcommit4087
3434 = [up to date] testcommit4088 -> origin/testcommit4088
3435 = [up to date] testcommit4089 -> origin/testcommit4089
3436 = [up to date] testcommit409 -> origin/testcommit409
3437 = [up to date] testcommit4090 -> origin/testcommit4090
3438 = [up to date] testcommit4091 -> origin/testcommit4091
3439 = [up to date] testcommit4092 -> origin/testcommit4092
3440 = [up to date] testcommit4093 -> origin/testcommit4093
3441 = [up to date] testcommit4094 -> origin/testcommit4094
3442 = [up to date] testcommit4095 -> origin/testcommit4095
3443 = [up to date] testcommit4096 -> origin/testcommit4096
3444 = [up to date] testcommit4097 -> origin/testcommit4097
3445 = [up to date] testcommit4098 -> origin/testcommit4098
3446 = [up to date] testcommit4099 -> origin/testcommit4099
3447 = [up to date] testcommit41 -> origin/testcommit41
3448 = [up to date] testcommit410 -> origin/testcommit410
3449 = [up to date] testcommit4100 -> origin/testcommit4100
3450 = [up to date] testcommit4101 -> origin/testcommit4101
3451 = [up to date] testcommit4102 -> origin/testcommit4102
3452 = [up to date] testcommit4103 -> origin/testcommit4103
3453 = [up to date] testcommit4104 -> origin/testcommit4104
3454 = [up to date] testcommit4105 -> origin/testcommit4105
3455 = [up to date] testcommit4106 -> origin/testcommit4106
3456 = [up to date] testcommit4107 -> origin/testcommit4107
3457 = [up to date] testcommit4108 -> origin/testcommit4108
3458 = [up to date] testcommit4109 -> origin/testcommit4109
3459 = [up to date] testcommit411 -> origin/testcommit411
3460 = [up to date] testcommit4110 -> origin/testcommit4110
3461 = [up to date] testcommit4111 -> origin/testcommit4111
3462 = [up to date] testcommit4112 -> origin/testcommit4112
3463 = [up to date] testcommit4113 -> origin/testcommit4113
3464 = [up to date] testcommit4114 -> origin/testcommit4114
3465 = [up to date] testcommit4115 -> origin/testcommit4115
3466 = [up to date] testcommit4116 -> origin/testcommit4116
3467 = [up to date] testcommit4117 -> origin/testcommit4117
3468 = [up to date] testcommit4118 -> origin/testcommit4118
3469 = [up to date] testcommit4119 -> origin/testcommit4119
3470 = [up to date] testcommit412 -> origin/testcommit412
3471 = [up to date] testcommit4120 -> origin/testcommit4120
3472 = [up to date] testcommit4121 -> origin/testcommit4121
3473 = [up to date] testcommit4122 -> origin/testcommit4122
3474 = [up to date] testcommit4123 -> origin/testcommit4123
3475 = [up to date] testcommit4124 -> origin/testcommit4124
3476 = [up to date] testcommit4125 -> origin/testcommit4125
3477 = [up to date] testcommit4126 -> origin/testcommit4126
3478 = [up to date] testcommit4127 -> origin/testcommit4127
3479 = [up to date] testcommit4128 -> origin/testcommit4128
3480 = [up to date] testcommit4129 -> origin/testcommit4129
3481 = [up to date] testcommit413 -> origin/testcommit413
3482 = [up to date] testcommit4130 -> origin/testcommit4130
3483 = [up to date] testcommit4131 -> origin/testcommit4131
3484 = [up to date] testcommit4132 -> origin/testcommit4132
3485 = [up to date] testcommit4133 -> origin/testcommit4133
3486 = [up to date] testcommit4134 -> origin/testcommit4134
3487 = [up to date] testcommit4135 -> origin/testcommit4135
3488 = [up to date] testcommit4136 -> origin/testcommit4136
3489 = [up to date] testcommit4137 -> origin/testcommit4137
3490 = [up to date] testcommit4138 -> origin/testcommit4138
3491 = [up to date] testcommit4139 -> origin/testcommit4139
3492 = [up to date] testcommit414 -> origin/testcommit414
3493 = [up to date] testcommit4140 -> origin/testcommit4140
3494 = [up to date] testcommit4141 -> origin/testcommit4141
3495 = [up to date] testcommit4142 -> origin/testcommit4142
3496 = [up to date] testcommit4143 -> origin/testcommit4143
3497 = [up to date] testcommit4144 -> origin/testcommit4144
3498 = [up to date] testcommit4145 -> origin/testcommit4145
3499 = [up to date] testcommit4146 -> origin/testcommit4146
3500 = [up to date] testcommit4147 -> origin/testcommit4147
3501 = [up to date] testcommit4148 -> origin/testcommit4148
3502 = [up to date] testcommit4149 -> origin/testcommit4149
3503 = [up to date] testcommit415 -> origin/testcommit415
3504 = [up to date] testcommit4150 -> origin/testcommit4150
3505 = [up to date] testcommit4151 -> origin/testcommit4151
3506 = [up to date] testcommit4152 -> origin/testcommit4152
3507 = [up to date] testcommit4153 -> origin/testcommit4153
3508 = [up to date] testcommit4154 -> origin/testcommit4154
3509 = [up to date] testcommit4155 -> origin/testcommit4155
3510 = [up to date] testcommit4156 -> origin/testcommit4156
3511 = [up to date] testcommit4157 -> origin/testcommit4157
3512 = [up to date] testcommit4158 -> origin/testcommit4158
3513 = [up to date] testcommit4159 -> origin/testcommit4159
3514 = [up to date] testcommit416 -> origin/testcommit416
3515 = [up to date] testcommit4160 -> origin/testcommit4160
3516 = [up to date] testcommit4161 -> origin/testcommit4161
3517 = [up to date] testcommit4162 -> origin/testcommit4162
3518 = [up to date] testcommit4163 -> origin/testcommit4163
3519 = [up to date] testcommit4164 -> origin/testcommit4164
3520 = [up to date] testcommit4165 -> origin/testcommit4165
3521 = [up to date] testcommit4166 -> origin/testcommit4166
3522 = [up to date] testcommit4167 -> origin/testcommit4167
3523 = [up to date] testcommit4168 -> origin/testcommit4168
3524 = [up to date] testcommit4169 -> origin/testcommit4169
3525 = [up to date] testcommit417 -> origin/testcommit417
3526 = [up to date] testcommit4170 -> origin/testcommit4170
3527 = [up to date] testcommit4171 -> origin/testcommit4171
3528 = [up to date] testcommit4172 -> origin/testcommit4172
3529 = [up to date] testcommit4173 -> origin/testcommit4173
3530 = [up to date] testcommit4174 -> origin/testcommit4174
3531 = [up to date] testcommit4175 -> origin/testcommit4175
3532 = [up to date] testcommit4176 -> origin/testcommit4176
3533 = [up to date] testcommit4177 -> origin/testcommit4177
3534 = [up to date] testcommit4178 -> origin/testcommit4178
3535 = [up to date] testcommit4179 -> origin/testcommit4179
3536 = [up to date] testcommit418 -> origin/testcommit418
3537 = [up to date] testcommit4180 -> origin/testcommit4180
3538 = [up to date] testcommit4181 -> origin/testcommit4181
3539 = [up to date] testcommit4182 -> origin/testcommit4182
3540 = [up to date] testcommit4183 -> origin/testcommit4183
3541 = [up to date] testcommit4184 -> origin/testcommit4184
3542 = [up to date] testcommit4185 -> origin/testcommit4185
3543 = [up to date] testcommit4186 -> origin/testcommit4186
3544 = [up to date] testcommit4187 -> origin/testcommit4187
3545 = [up to date] testcommit4188 -> origin/testcommit4188
3546 = [up to date] testcommit4189 -> origin/testcommit4189
3547 = [up to date] testcommit419 -> origin/testcommit419
3548 = [up to date] testcommit4190 -> origin/testcommit4190
3549 = [up to date] testcommit4191 -> origin/testcommit4191
3550 = [up to date] testcommit4192 -> origin/testcommit4192
3551 = [up to date] testcommit4193 -> origin/testcommit4193
3552 = [up to date] testcommit4194 -> origin/testcommit4194
3553 = [up to date] testcommit4195 -> origin/testcommit4195
3554 = [up to date] testcommit4196 -> origin/testcommit4196
3555 = [up to date] testcommit4197 -> origin/testcommit4197
3556 = [up to date] testcommit4198 -> origin/testcommit4198
3557 = [up to date] testcommit4199 -> origin/testcommit4199
3558 = [up to date] testcommit42 -> origin/testcommit42
3559 = [up to date] testcommit420 -> origin/testcommit420
3560 = [up to date] testcommit4200 -> origin/testcommit4200
3561 = [up to date] testcommit4201 -> origin/testcommit4201
3562 = [up to date] testcommit4202 -> origin/testcommit4202
3563 = [up to date] testcommit4203 -> origin/testcommit4203
3564 = [up to date] testcommit4204 -> origin/testcommit4204
3565 = [up to date] testcommit4205 -> origin/testcommit4205
3566 = [up to date] testcommit4206 -> origin/testcommit4206
3567 = [up to date] testcommit4207 -> origin/testcommit4207
3568 = [up to date] testcommit4208 -> origin/testcommit4208
3569 = [up to date] testcommit4209 -> origin/testcommit4209
3570 = [up to date] testcommit421 -> origin/testcommit421
3571 = [up to date] testcommit4210 -> origin/testcommit4210
3572 = [up to date] testcommit4211 -> origin/testcommit4211
3573 = [up to date] testcommit4212 -> origin/testcommit4212
3574 = [up to date] testcommit4213 -> origin/testcommit4213
3575 = [up to date] testcommit4214 -> origin/testcommit4214
3576 = [up to date] testcommit4215 -> origin/testcommit4215
3577 = [up to date] testcommit4216 -> origin/testcommit4216
3578 = [up to date] testcommit4217 -> origin/testcommit4217
3579 = [up to date] testcommit4218 -> origin/testcommit4218
3580 = [up to date] testcommit4219 -> origin/testcommit4219
3581 = [up to date] testcommit422 -> origin/testcommit422
3582 = [up to date] testcommit4220 -> origin/testcommit4220
3583 = [up to date] testcommit4221 -> origin/testcommit4221
3584 = [up to date] testcommit4222 -> origin/testcommit4222
3585 = [up to date] testcommit4223 -> origin/testcommit4223
3586 = [up to date] testcommit4224 -> origin/testcommit4224
3587 = [up to date] testcommit4225 -> origin/testcommit4225
3588 = [up to date] testcommit4226 -> origin/testcommit4226
3589 = [up to date] testcommit4227 -> origin/testcommit4227
3590 = [up to date] testcommit4228 -> origin/testcommit4228
3591 = [up to date] testcommit4229 -> origin/testcommit4229
3592 = [up to date] testcommit423 -> origin/testcommit423
3593 = [up to date] testcommit4230 -> origin/testcommit4230
3594 = [up to date] testcommit4231 -> origin/testcommit4231
3595 = [up to date] testcommit4232 -> origin/testcommit4232
3596 = [up to date] testcommit4233 -> origin/testcommit4233
3597 = [up to date] testcommit4234 -> origin/testcommit4234
3598 = [up to date] testcommit4235 -> origin/testcommit4235
3599 = [up to date] testcommit4236 -> origin/testcommit4236
3600 = [up to date] testcommit4237 -> origin/testcommit4237
3601 = [up to date] testcommit4238 -> origin/testcommit4238
3602 = [up to date] testcommit4239 -> origin/testcommit4239
3603 = [up to date] testcommit424 -> origin/testcommit424
3604 = [up to date] testcommit4240 -> origin/testcommit4240
3605 = [up to date] testcommit4241 -> origin/testcommit4241
3606 = [up to date] testcommit4242 -> origin/testcommit4242
3607 = [up to date] testcommit4243 -> origin/testcommit4243
3608 = [up to date] testcommit4244 -> origin/testcommit4244
3609 = [up to date] testcommit4245 -> origin/testcommit4245
3610 = [up to date] testcommit4246 -> origin/testcommit4246
3611 = [up to date] testcommit4247 -> origin/testcommit4247
3612 = [up to date] testcommit4248 -> origin/testcommit4248
3613 = [up to date] testcommit4249 -> origin/testcommit4249
3614 = [up to date] testcommit425 -> origin/testcommit425
3615 = [up to date] testcommit4250 -> origin/testcommit4250
3616 = [up to date] testcommit4251 -> origin/testcommit4251
3617 = [up to date] testcommit4252 -> origin/testcommit4252
3618 = [up to date] testcommit4253 -> origin/testcommit4253
3619 = [up to date] testcommit4254 -> origin/testcommit4254
3620 = [up to date] testcommit4255 -> origin/testcommit4255
3621 = [up to date] testcommit4256 -> origin/testcommit4256
3622 = [up to date] testcommit4257 -> origin/testcommit4257
3623 = [up to date] testcommit4258 -> origin/testcommit4258
3624 = [up to date] testcommit4259 -> origin/testcommit4259
3625 = [up to date] testcommit426 -> origin/testcommit426
3626 = [up to date] testcommit4260 -> origin/testcommit4260
3627 = [up to date] testcommit4261 -> origin/testcommit4261
3628 = [up to date] testcommit4262 -> origin/testcommit4262
3629 = [up to date] testcommit4263 -> origin/testcommit4263
3630 = [up to date] testcommit4264 -> origin/testcommit4264
3631 = [up to date] testcommit4265 -> origin/testcommit4265
3632 = [up to date] testcommit4266 -> origin/testcommit4266
3633 = [up to date] testcommit4267 -> origin/testcommit4267
3634 = [up to date] testcommit4268 -> origin/testcommit4268
3635 = [up to date] testcommit4269 -> origin/testcommit4269
3636 = [up to date] testcommit427 -> origin/testcommit427
3637 = [up to date] testcommit4270 -> origin/testcommit4270
3638 = [up to date] testcommit4271 -> origin/testcommit4271
3639 = [up to date] testcommit4272 -> origin/testcommit4272
3640 = [up to date] testcommit4273 -> origin/testcommit4273
3641 = [up to date] testcommit4274 -> origin/testcommit4274
3642 = [up to date] testcommit4275 -> origin/testcommit4275
3643 = [up to date] testcommit4276 -> origin/testcommit4276
3644 = [up to date] testcommit4277 -> origin/testcommit4277
3645 = [up to date] testcommit4278 -> origin/testcommit4278
3646 = [up to date] testcommit4279 -> origin/testcommit4279
3647 = [up to date] testcommit428 -> origin/testcommit428
3648 = [up to date] testcommit4280 -> origin/testcommit4280
3649 = [up to date] testcommit4281 -> origin/testcommit4281
3650 = [up to date] testcommit4282 -> origin/testcommit4282
3651 = [up to date] testcommit4283 -> origin/testcommit4283
3652 = [up to date] testcommit4284 -> origin/testcommit4284
3653 = [up to date] testcommit4285 -> origin/testcommit4285
3654 = [up to date] testcommit4286 -> origin/testcommit4286
3655 = [up to date] testcommit4287 -> origin/testcommit4287
3656 = [up to date] testcommit4288 -> origin/testcommit4288
3657 = [up to date] testcommit4289 -> origin/testcommit4289
3658 = [up to date] testcommit429 -> origin/testcommit429
3659 = [up to date] testcommit4290 -> origin/testcommit4290
3660 = [up to date] testcommit4291 -> origin/testcommit4291
3661 = [up to date] testcommit4292 -> origin/testcommit4292
3662 = [up to date] testcommit4293 -> origin/testcommit4293
3663 = [up to date] testcommit4294 -> origin/testcommit4294
3664 = [up to date] testcommit4295 -> origin/testcommit4295
3665 = [up to date] testcommit4296 -> origin/testcommit4296
3666 = [up to date] testcommit4297 -> origin/testcommit4297
3667 = [up to date] testcommit4298 -> origin/testcommit4298
3668 = [up to date] testcommit4299 -> origin/testcommit4299
3669 = [up to date] testcommit43 -> origin/testcommit43
3670 = [up to date] testcommit430 -> origin/testcommit430
3671 = [up to date] testcommit4300 -> origin/testcommit4300
3672 = [up to date] testcommit4301 -> origin/testcommit4301
3673 = [up to date] testcommit4302 -> origin/testcommit4302
3674 = [up to date] testcommit4303 -> origin/testcommit4303
3675 = [up to date] testcommit4304 -> origin/testcommit4304
3676 = [up to date] testcommit4305 -> origin/testcommit4305
3677 = [up to date] testcommit4306 -> origin/testcommit4306
3678 = [up to date] testcommit4307 -> origin/testcommit4307
3679 = [up to date] testcommit4308 -> origin/testcommit4308
3680 = [up to date] testcommit4309 -> origin/testcommit4309
3681 = [up to date] testcommit431 -> origin/testcommit431
3682 = [up to date] testcommit4310 -> origin/testcommit4310
3683 = [up to date] testcommit4311 -> origin/testcommit4311
3684 = [up to date] testcommit4312 -> origin/testcommit4312
3685 = [up to date] testcommit4313 -> origin/testcommit4313
3686 = [up to date] testcommit4314 -> origin/testcommit4314
3687 = [up to date] testcommit4315 -> origin/testcommit4315
3688 = [up to date] testcommit4316 -> origin/testcommit4316
3689 = [up to date] testcommit4317 -> origin/testcommit4317
3690 = [up to date] testcommit4318 -> origin/testcommit4318
3691 = [up to date] testcommit4319 -> origin/testcommit4319
3692 = [up to date] testcommit432 -> origin/testcommit432
3693 = [up to date] testcommit4320 -> origin/testcommit4320
3694 = [up to date] testcommit4321 -> origin/testcommit4321
3695 = [up to date] testcommit4322 -> origin/testcommit4322
3696 = [up to date] testcommit4323 -> origin/testcommit4323
3697 = [up to date] testcommit4324 -> origin/testcommit4324
3698 = [up to date] testcommit4325 -> origin/testcommit4325
3699 = [up to date] testcommit4326 -> origin/testcommit4326
3700 = [up to date] testcommit4327 -> origin/testcommit4327
3701 = [up to date] testcommit4328 -> origin/testcommit4328
3702 = [up to date] testcommit4329 -> origin/testcommit4329
3703 = [up to date] testcommit433 -> origin/testcommit433
3704 = [up to date] testcommit4330 -> origin/testcommit4330
3705 = [up to date] testcommit4331 -> origin/testcommit4331
3706 = [up to date] testcommit4332 -> origin/testcommit4332
3707 = [up to date] testcommit4333 -> origin/testcommit4333
3708 = [up to date] testcommit4334 -> origin/testcommit4334
3709 = [up to date] testcommit4335 -> origin/testcommit4335
3710 = [up to date] testcommit4336 -> origin/testcommit4336
3711 = [up to date] testcommit4337 -> origin/testcommit4337
3712 = [up to date] testcommit4338 -> origin/testcommit4338
3713 = [up to date] testcommit4339 -> origin/testcommit4339
3714 = [up to date] testcommit434 -> origin/testcommit434
3715 = [up to date] testcommit4340 -> origin/testcommit4340
3716 = [up to date] testcommit4341 -> origin/testcommit4341
3717 = [up to date] testcommit4342 -> origin/testcommit4342
3718 = [up to date] testcommit4343 -> origin/testcommit4343
3719 = [up to date] testcommit4344 -> origin/testcommit4344
3720 = [up to date] testcommit4345 -> origin/testcommit4345
3721 = [up to date] testcommit4346 -> origin/testcommit4346
3722 = [up to date] testcommit4347 -> origin/testcommit4347
3723 = [up to date] testcommit4348 -> origin/testcommit4348
3724 = [up to date] testcommit4349 -> origin/testcommit4349
3725 = [up to date] testcommit435 -> origin/testcommit435
3726 = [up to date] testcommit4350 -> origin/testcommit4350
3727 = [up to date] testcommit4351 -> origin/testcommit4351
3728 = [up to date] testcommit4352 -> origin/testcommit4352
3729 = [up to date] testcommit4353 -> origin/testcommit4353
3730 = [up to date] testcommit4354 -> origin/testcommit4354
3731 = [up to date] testcommit4355 -> origin/testcommit4355
3732 = [up to date] testcommit4356 -> origin/testcommit4356
3733 = [up to date] testcommit4357 -> origin/testcommit4357
3734 = [up to date] testcommit4358 -> origin/testcommit4358
3735 = [up to date] testcommit4359 -> origin/testcommit4359
3736 = [up to date] testcommit436 -> origin/testcommit436
3737 = [up to date] testcommit4360 -> origin/testcommit4360
3738 = [up to date] testcommit4361 -> origin/testcommit4361
3739 = [up to date] testcommit4362 -> origin/testcommit4362
3740 = [up to date] testcommit4363 -> origin/testcommit4363
3741 = [up to date] testcommit4364 -> origin/testcommit4364
3742 = [up to date] testcommit4365 -> origin/testcommit4365
3743 = [up to date] testcommit4366 -> origin/testcommit4366
3744 = [up to date] testcommit4367 -> origin/testcommit4367
3745 = [up to date] testcommit4368 -> origin/testcommit4368
3746 = [up to date] testcommit4369 -> origin/testcommit4369
3747 = [up to date] testcommit437 -> origin/testcommit437
3748 = [up to date] testcommit4370 -> origin/testcommit4370
3749 = [up to date] testcommit4371 -> origin/testcommit4371
3750 = [up to date] testcommit4372 -> origin/testcommit4372
3751 = [up to date] testcommit4373 -> origin/testcommit4373
3752 = [up to date] testcommit4374 -> origin/testcommit4374
3753 = [up to date] testcommit4375 -> origin/testcommit4375
3754 = [up to date] testcommit4376 -> origin/testcommit4376
3755 = [up to date] testcommit4377 -> origin/testcommit4377
3756 = [up to date] testcommit4378 -> origin/testcommit4378
3757 = [up to date] testcommit4379 -> origin/testcommit4379
3758 = [up to date] testcommit438 -> origin/testcommit438
3759 = [up to date] testcommit4380 -> origin/testcommit4380
3760 = [up to date] testcommit4381 -> origin/testcommit4381
3761 = [up to date] testcommit4382 -> origin/testcommit4382
3762 = [up to date] testcommit4383 -> origin/testcommit4383
3763 = [up to date] testcommit4384 -> origin/testcommit4384
3764 = [up to date] testcommit4385 -> origin/testcommit4385
3765 = [up to date] testcommit4386 -> origin/testcommit4386
3766 = [up to date] testcommit4387 -> origin/testcommit4387
3767 = [up to date] testcommit4388 -> origin/testcommit4388
3768 = [up to date] testcommit4389 -> origin/testcommit4389
3769 = [up to date] testcommit439 -> origin/testcommit439
3770 = [up to date] testcommit4390 -> origin/testcommit4390
3771 = [up to date] testcommit4391 -> origin/testcommit4391
3772 = [up to date] testcommit4392 -> origin/testcommit4392
3773 = [up to date] testcommit4393 -> origin/testcommit4393
3774 = [up to date] testcommit4394 -> origin/testcommit4394
3775 = [up to date] testcommit4395 -> origin/testcommit4395
3776 = [up to date] testcommit4396 -> origin/testcommit4396
3777 = [up to date] testcommit4397 -> origin/testcommit4397
3778 = [up to date] testcommit4398 -> origin/testcommit4398
3779 = [up to date] testcommit4399 -> origin/testcommit4399
3780 = [up to date] testcommit44 -> origin/testcommit44
3781 = [up to date] testcommit440 -> origin/testcommit440
3782 = [up to date] testcommit4400 -> origin/testcommit4400
3783 = [up to date] testcommit4401 -> origin/testcommit4401
3784 = [up to date] testcommit4402 -> origin/testcommit4402
3785 = [up to date] testcommit4403 -> origin/testcommit4403
3786 = [up to date] testcommit4404 -> origin/testcommit4404
3787 = [up to date] testcommit4405 -> origin/testcommit4405
3788 = [up to date] testcommit4406 -> origin/testcommit4406
3789 = [up to date] testcommit4407 -> origin/testcommit4407
3790 = [up to date] testcommit4408 -> origin/testcommit4408
3791 = [up to date] testcommit4409 -> origin/testcommit4409
3792 = [up to date] testcommit441 -> origin/testcommit441
3793 = [up to date] testcommit4410 -> origin/testcommit4410
3794 = [up to date] testcommit4411 -> origin/testcommit4411
3795 = [up to date] testcommit4412 -> origin/testcommit4412
3796 = [up to date] testcommit4413 -> origin/testcommit4413
3797 = [up to date] testcommit4414 -> origin/testcommit4414
3798 = [up to date] testcommit4415 -> origin/testcommit4415
3799 = [up to date] testcommit4416 -> origin/testcommit4416
3800 = [up to date] testcommit4417 -> origin/testcommit4417
3801 = [up to date] testcommit4418 -> origin/testcommit4418
3802 = [up to date] testcommit4419 -> origin/testcommit4419
3803 = [up to date] testcommit442 -> origin/testcommit442
3804 = [up to date] testcommit4420 -> origin/testcommit4420
3805 = [up to date] testcommit4421 -> origin/testcommit4421
3806 = [up to date] testcommit4422 -> origin/testcommit4422
3807 = [up to date] testcommit4423 -> origin/testcommit4423
3808 = [up to date] testcommit4424 -> origin/testcommit4424
3809 = [up to date] testcommit4425 -> origin/testcommit4425
3810 = [up to date] testcommit4426 -> origin/testcommit4426
3811 = [up to date] testcommit4427 -> origin/testcommit4427
3812 = [up to date] testcommit4428 -> origin/testcommit4428
3813 = [up to date] testcommit4429 -> origin/testcommit4429
3814 = [up to date] testcommit443 -> origin/testcommit443
3815 = [up to date] testcommit4430 -> origin/testcommit4430
3816 = [up to date] testcommit4431 -> origin/testcommit4431
3817 = [up to date] testcommit4432 -> origin/testcommit4432
3818 = [up to date] testcommit4433 -> origin/testcommit4433
3819 = [up to date] testcommit4434 -> origin/testcommit4434
3820 = [up to date] testcommit4435 -> origin/testcommit4435
3821 = [up to date] testcommit4436 -> origin/testcommit4436
3822 = [up to date] testcommit4437 -> origin/testcommit4437
3823 = [up to date] testcommit4438 -> origin/testcommit4438
3824 = [up to date] testcommit4439 -> origin/testcommit4439
3825 = [up to date] testcommit444 -> origin/testcommit444
3826 = [up to date] testcommit4440 -> origin/testcommit4440
3827 = [up to date] testcommit4441 -> origin/testcommit4441
3828 = [up to date] testcommit4442 -> origin/testcommit4442
3829 = [up to date] testcommit4443 -> origin/testcommit4443
3830 = [up to date] testcommit4444 -> origin/testcommit4444
3831 = [up to date] testcommit4445 -> origin/testcommit4445
3832 = [up to date] testcommit4446 -> origin/testcommit4446
3833 = [up to date] testcommit4447 -> origin/testcommit4447
3834 = [up to date] testcommit4448 -> origin/testcommit4448
3835 = [up to date] testcommit4449 -> origin/testcommit4449
3836 = [up to date] testcommit445 -> origin/testcommit445
3837 = [up to date] testcommit4450 -> origin/testcommit4450
3838 = [up to date] testcommit4451 -> origin/testcommit4451
3839 = [up to date] testcommit4452 -> origin/testcommit4452
3840 = [up to date] testcommit4453 -> origin/testcommit4453
3841 = [up to date] testcommit4454 -> origin/testcommit4454
3842 = [up to date] testcommit4455 -> origin/testcommit4455
3843 = [up to date] testcommit4456 -> origin/testcommit4456
3844 = [up to date] testcommit4457 -> origin/testcommit4457
3845 = [up to date] testcommit4458 -> origin/testcommit4458
3846 = [up to date] testcommit4459 -> origin/testcommit4459
3847 = [up to date] testcommit446 -> origin/testcommit446
3848 = [up to date] testcommit4460 -> origin/testcommit4460
3849 = [up to date] testcommit4461 -> origin/testcommit4461
3850 = [up to date] testcommit4462 -> origin/testcommit4462
3851 = [up to date] testcommit4463 -> origin/testcommit4463
3852 = [up to date] testcommit4464 -> origin/testcommit4464
3853 = [up to date] testcommit4465 -> origin/testcommit4465
3854 = [up to date] testcommit4466 -> origin/testcommit4466
3855 = [up to date] testcommit4467 -> origin/testcommit4467
3856 = [up to date] testcommit4468 -> origin/testcommit4468
3857 = [up to date] testcommit4469 -> origin/testcommit4469
3858 = [up to date] testcommit447 -> origin/testcommit447
3859 = [up to date] testcommit4470 -> origin/testcommit4470
3860 = [up to date] testcommit4471 -> origin/testcommit4471
3861 = [up to date] testcommit4472 -> origin/testcommit4472
3862 = [up to date] testcommit4473 -> origin/testcommit4473
3863 = [up to date] testcommit4474 -> origin/testcommit4474
3864 = [up to date] testcommit4475 -> origin/testcommit4475
3865 = [up to date] testcommit4476 -> origin/testcommit4476
3866 = [up to date] testcommit4477 -> origin/testcommit4477
3867 = [up to date] testcommit4478 -> origin/testcommit4478
3868 = [up to date] testcommit4479 -> origin/testcommit4479
3869 = [up to date] testcommit448 -> origin/testcommit448
3870 = [up to date] testcommit4480 -> origin/testcommit4480
3871 = [up to date] testcommit4481 -> origin/testcommit4481
3872 = [up to date] testcommit4482 -> origin/testcommit4482
3873 = [up to date] testcommit4483 -> origin/testcommit4483
3874 = [up to date] testcommit4484 -> origin/testcommit4484
3875 = [up to date] testcommit4485 -> origin/testcommit4485
3876 = [up to date] testcommit4486 -> origin/testcommit4486
3877 = [up to date] testcommit4487 -> origin/testcommit4487
3878 = [up to date] testcommit4488 -> origin/testcommit4488
3879 = [up to date] testcommit4489 -> origin/testcommit4489
3880 = [up to date] testcommit449 -> origin/testcommit449
3881 = [up to date] testcommit4490 -> origin/testcommit4490
3882 = [up to date] testcommit4491 -> origin/testcommit4491
3883 = [up to date] testcommit4492 -> origin/testcommit4492
3884 = [up to date] testcommit4493 -> origin/testcommit4493
3885 = [up to date] testcommit4494 -> origin/testcommit4494
3886 = [up to date] testcommit4495 -> origin/testcommit4495
3887 = [up to date] testcommit4496 -> origin/testcommit4496
3888 = [up to date] testcommit4497 -> origin/testcommit4497
3889 = [up to date] testcommit4498 -> origin/testcommit4498
3890 = [up to date] testcommit4499 -> origin/testcommit4499
3891 = [up to date] testcommit45 -> origin/testcommit45
3892 = [up to date] testcommit450 -> origin/testcommit450
3893 = [up to date] testcommit4500 -> origin/testcommit4500
3894 = [up to date] testcommit4501 -> origin/testcommit4501
3895 = [up to date] testcommit4502 -> origin/testcommit4502
3896 = [up to date] testcommit4503 -> origin/testcommit4503
3897 = [up to date] testcommit4504 -> origin/testcommit4504
3898 = [up to date] testcommit4505 -> origin/testcommit4505
3899 = [up to date] testcommit4506 -> origin/testcommit4506
3900 = [up to date] testcommit4507 -> origin/testcommit4507
3901 = [up to date] testcommit4508 -> origin/testcommit4508
3902 = [up to date] testcommit4509 -> origin/testcommit4509
3903 = [up to date] testcommit451 -> origin/testcommit451
3904 = [up to date] testcommit4510 -> origin/testcommit4510
3905 = [up to date] testcommit4511 -> origin/testcommit4511
3906 = [up to date] testcommit4512 -> origin/testcommit4512
3907 = [up to date] testcommit4513 -> origin/testcommit4513
3908 = [up to date] testcommit4514 -> origin/testcommit4514
3909 = [up to date] testcommit4515 -> origin/testcommit4515
3910 = [up to date] testcommit4516 -> origin/testcommit4516
3911 = [up to date] testcommit4517 -> origin/testcommit4517
3912 = [up to date] testcommit4518 -> origin/testcommit4518
3913 = [up to date] testcommit4519 -> origin/testcommit4519
3914 = [up to date] testcommit452 -> origin/testcommit452
3915 = [up to date] testcommit4520 -> origin/testcommit4520
3916 = [up to date] testcommit4521 -> origin/testcommit4521
3917 = [up to date] testcommit4522 -> origin/testcommit4522
3918 = [up to date] testcommit4523 -> origin/testcommit4523
3919 = [up to date] testcommit4524 -> origin/testcommit4524
3920 = [up to date] testcommit4525 -> origin/testcommit4525
3921 = [up to date] testcommit4526 -> origin/testcommit4526
3922 = [up to date] testcommit4527 -> origin/testcommit4527
3923 = [up to date] testcommit4528 -> origin/testcommit4528
3924 = [up to date] testcommit4529 -> origin/testcommit4529
3925 = [up to date] testcommit453 -> origin/testcommit453
3926 = [up to date] testcommit4530 -> origin/testcommit4530
3927 = [up to date] testcommit4531 -> origin/testcommit4531
3928 = [up to date] testcommit4532 -> origin/testcommit4532
3929 = [up to date] testcommit4533 -> origin/testcommit4533
3930 = [up to date] testcommit4534 -> origin/testcommit4534
3931 = [up to date] testcommit4535 -> origin/testcommit4535
3932 = [up to date] testcommit4536 -> origin/testcommit4536
3933 = [up to date] testcommit4537 -> origin/testcommit4537
3934 = [up to date] testcommit4538 -> origin/testcommit4538
3935 = [up to date] testcommit4539 -> origin/testcommit4539
3936 = [up to date] testcommit454 -> origin/testcommit454
3937 = [up to date] testcommit4540 -> origin/testcommit4540
3938 = [up to date] testcommit4541 -> origin/testcommit4541
3939 = [up to date] testcommit4542 -> origin/testcommit4542
3940 = [up to date] testcommit4543 -> origin/testcommit4543
3941 = [up to date] testcommit4544 -> origin/testcommit4544
3942 = [up to date] testcommit4545 -> origin/testcommit4545
3943 = [up to date] testcommit4546 -> origin/testcommit4546
3944 = [up to date] testcommit4547 -> origin/testcommit4547
3945 = [up to date] testcommit4548 -> origin/testcommit4548
3946 = [up to date] testcommit4549 -> origin/testcommit4549
3947 = [up to date] testcommit455 -> origin/testcommit455
3948 = [up to date] testcommit4550 -> origin/testcommit4550
3949 = [up to date] testcommit4551 -> origin/testcommit4551
3950 = [up to date] testcommit4552 -> origin/testcommit4552
3951 = [up to date] testcommit4553 -> origin/testcommit4553
3952 = [up to date] testcommit4554 -> origin/testcommit4554
3953 = [up to date] testcommit4555 -> origin/testcommit4555
3954 = [up to date] testcommit4556 -> origin/testcommit4556
3955 = [up to date] testcommit4557 -> origin/testcommit4557
3956 = [up to date] testcommit4558 -> origin/testcommit4558
3957 = [up to date] testcommit4559 -> origin/testcommit4559
3958 = [up to date] testcommit456 -> origin/testcommit456
3959 = [up to date] testcommit4560 -> origin/testcommit4560
3960 = [up to date] testcommit4561 -> origin/testcommit4561
3961 = [up to date] testcommit4562 -> origin/testcommit4562
3962 = [up to date] testcommit4563 -> origin/testcommit4563
3963 = [up to date] testcommit4564 -> origin/testcommit4564
3964 = [up to date] testcommit4565 -> origin/testcommit4565
3965 = [up to date] testcommit4566 -> origin/testcommit4566
3966 = [up to date] testcommit4567 -> origin/testcommit4567
3967 = [up to date] testcommit4568 -> origin/testcommit4568
3968 = [up to date] testcommit4569 -> origin/testcommit4569
3969 = [up to date] testcommit457 -> origin/testcommit457
3970 = [up to date] testcommit4570 -> origin/testcommit4570
3971 = [up to date] testcommit4571 -> origin/testcommit4571
3972 = [up to date] testcommit4572 -> origin/testcommit4572
3973 = [up to date] testcommit4573 -> origin/testcommit4573
3974 = [up to date] testcommit4574 -> origin/testcommit4574
3975 = [up to date] testcommit4575 -> origin/testcommit4575
3976 = [up to date] testcommit4576 -> origin/testcommit4576
3977 = [up to date] testcommit4577 -> origin/testcommit4577
3978 = [up to date] testcommit4578 -> origin/testcommit4578
3979 = [up to date] testcommit4579 -> origin/testcommit4579
3980 = [up to date] testcommit458 -> origin/testcommit458
3981 = [up to date] testcommit4580 -> origin/testcommit4580
3982 = [up to date] testcommit4581 -> origin/testcommit4581
3983 = [up to date] testcommit4582 -> origin/testcommit4582
3984 = [up to date] testcommit4583 -> origin/testcommit4583
3985 = [up to date] testcommit4584 -> origin/testcommit4584
3986 = [up to date] testcommit4585 -> origin/testcommit4585
3987 = [up to date] testcommit4586 -> origin/testcommit4586
3988 = [up to date] testcommit4587 -> origin/testcommit4587
3989 = [up to date] testcommit4588 -> origin/testcommit4588
3990 = [up to date] testcommit4589 -> origin/testcommit4589
3991 = [up to date] testcommit459 -> origin/testcommit459
3992 = [up to date] testcommit4590 -> origin/testcommit4590
3993 = [up to date] testcommit4591 -> origin/testcommit4591
3994 = [up to date] testcommit4592 -> origin/testcommit4592
3995 = [up to date] testcommit4593 -> origin/testcommit4593
3996 = [up to date] testcommit4594 -> origin/testcommit4594
3997 = [up to date] testcommit4595 -> origin/testcommit4595
3998 = [up to date] testcommit4596 -> origin/testcommit4596
3999 = [up to date] testcommit4597 -> origin/testcommit4597
4000 = [up to date] testcommit4598 -> origin/testcommit4598
4001 = [up to date] testcommit4599 -> origin/testcommit4599
4002 = [up to date] testcommit46 -> origin/testcommit46
4003 = [up to date] testcommit460 -> origin/testcommit460
4004 = [up to date] testcommit4600 -> origin/testcommit4600
4005 = [up to date] testcommit4601 -> origin/testcommit4601
4006 = [up to date] testcommit4602 -> origin/testcommit4602
4007 = [up to date] testcommit4603 -> origin/testcommit4603
4008 = [up to date] testcommit4604 -> origin/testcommit4604
4009 = [up to date] testcommit4605 -> origin/testcommit4605
4010 = [up to date] testcommit4606 -> origin/testcommit4606
4011 = [up to date] testcommit4607 -> origin/testcommit4607
4012 = [up to date] testcommit4608 -> origin/testcommit4608
4013 = [up to date] testcommit4609 -> origin/testcommit4609
4014 = [up to date] testcommit461 -> origin/testcommit461
4015 = [up to date] testcommit4610 -> origin/testcommit4610
4016 = [up to date] testcommit4611 -> origin/testcommit4611
4017 = [up to date] testcommit4612 -> origin/testcommit4612
4018 = [up to date] testcommit4613 -> origin/testcommit4613
4019 = [up to date] testcommit4614 -> origin/testcommit4614
4020 = [up to date] testcommit4615 -> origin/testcommit4615
4021 = [up to date] testcommit4616 -> origin/testcommit4616
4022 = [up to date] testcommit4617 -> origin/testcommit4617
4023 = [up to date] testcommit4618 -> origin/testcommit4618
4024 = [up to date] testcommit4619 -> origin/testcommit4619
4025 = [up to date] testcommit462 -> origin/testcommit462
4026 = [up to date] testcommit4620 -> origin/testcommit4620
4027 = [up to date] testcommit4621 -> origin/testcommit4621
4028 = [up to date] testcommit4622 -> origin/testcommit4622
4029 = [up to date] testcommit4623 -> origin/testcommit4623
4030 = [up to date] testcommit4624 -> origin/testcommit4624
4031 = [up to date] testcommit4625 -> origin/testcommit4625
4032 = [up to date] testcommit4626 -> origin/testcommit4626
4033 = [up to date] testcommit4627 -> origin/testcommit4627
4034 = [up to date] testcommit4628 -> origin/testcommit4628
4035 = [up to date] testcommit4629 -> origin/testcommit4629
4036 = [up to date] testcommit463 -> origin/testcommit463
4037 = [up to date] testcommit4630 -> origin/testcommit4630
4038 = [up to date] testcommit4631 -> origin/testcommit4631
4039 = [up to date] testcommit4632 -> origin/testcommit4632
4040 = [up to date] testcommit4633 -> origin/testcommit4633
4041 = [up to date] testcommit4634 -> origin/testcommit4634
4042 = [up to date] testcommit4635 -> origin/testcommit4635
4043 = [up to date] testcommit4636 -> origin/testcommit4636
4044 = [up to date] testcommit4637 -> origin/testcommit4637
4045 = [up to date] testcommit4638 -> origin/testcommit4638
4046 = [up to date] testcommit4639 -> origin/testcommit4639
4047 = [up to date] testcommit464 -> origin/testcommit464
4048 = [up to date] testcommit4640 -> origin/testcommit4640
4049 = [up to date] testcommit4641 -> origin/testcommit4641
4050 = [up to date] testcommit4642 -> origin/testcommit4642
4051 = [up to date] testcommit4643 -> origin/testcommit4643
4052 = [up to date] testcommit4644 -> origin/testcommit4644
4053 = [up to date] testcommit4645 -> origin/testcommit4645
4054 = [up to date] testcommit4646 -> origin/testcommit4646
4055 = [up to date] testcommit4647 -> origin/testcommit4647
4056 = [up to date] testcommit4648 -> origin/testcommit4648
4057 = [up to date] testcommit4649 -> origin/testcommit4649
4058 = [up to date] testcommit465 -> origin/testcommit465
4059 = [up to date] testcommit4650 -> origin/testcommit4650
4060 = [up to date] testcommit4651 -> origin/testcommit4651
4061 = [up to date] testcommit4652 -> origin/testcommit4652
4062 = [up to date] testcommit4653 -> origin/testcommit4653
4063 = [up to date] testcommit4654 -> origin/testcommit4654
4064 = [up to date] testcommit4655 -> origin/testcommit4655
4065 = [up to date] testcommit4656 -> origin/testcommit4656
4066 = [up to date] testcommit4657 -> origin/testcommit4657
4067 = [up to date] testcommit4658 -> origin/testcommit4658
4068 = [up to date] testcommit4659 -> origin/testcommit4659
4069 = [up to date] testcommit466 -> origin/testcommit466
4070 = [up to date] testcommit4660 -> origin/testcommit4660
4071 = [up to date] testcommit4661 -> origin/testcommit4661
4072 = [up to date] testcommit4662 -> origin/testcommit4662
4073 = [up to date] testcommit4663 -> origin/testcommit4663
4074 = [up to date] testcommit4664 -> origin/testcommit4664
4075 = [up to date] testcommit4665 -> origin/testcommit4665
4076 = [up to date] testcommit4666 -> origin/testcommit4666
4077 = [up to date] testcommit4667 -> origin/testcommit4667
4078 = [up to date] testcommit4668 -> origin/testcommit4668
4079 = [up to date] testcommit4669 -> origin/testcommit4669
4080 = [up to date] testcommit467 -> origin/testcommit467
4081 = [up to date] testcommit4670 -> origin/testcommit4670
4082 = [up to date] testcommit4671 -> origin/testcommit4671
4083 = [up to date] testcommit4672 -> origin/testcommit4672
4084 = [up to date] testcommit4673 -> origin/testcommit4673
4085 = [up to date] testcommit4674 -> origin/testcommit4674
4086 = [up to date] testcommit4675 -> origin/testcommit4675
4087 = [up to date] testcommit4676 -> origin/testcommit4676
4088 = [up to date] testcommit4677 -> origin/testcommit4677
4089 = [up to date] testcommit4678 -> origin/testcommit4678
4090 = [up to date] testcommit4679 -> origin/testcommit4679
4091 = [up to date] testcommit468 -> origin/testcommit468
4092 = [up to date] testcommit4680 -> origin/testcommit4680
4093 = [up to date] testcommit4681 -> origin/testcommit4681
4094 = [up to date] testcommit4682 -> origin/testcommit4682
4095 = [up to date] testcommit4683 -> origin/testcommit4683
4096 = [up to date] testcommit4684 -> origin/testcommit4684
4097 = [up to date] testcommit4685 -> origin/testcommit4685
4098 = [up to date] testcommit4686 -> origin/testcommit4686
4099 = [up to date] testcommit4687 -> origin/testcommit4687
4100 = [up to date] testcommit4688 -> origin/testcommit4688
4101 = [up to date] testcommit4689 -> origin/testcommit4689
4102 = [up to date] testcommit469 -> origin/testcommit469
4103 = [up to date] testcommit4690 -> origin/testcommit4690
4104 = [up to date] testcommit4691 -> origin/testcommit4691
4105 = [up to date] testcommit4692 -> origin/testcommit4692
4106 = [up to date] testcommit4693 -> origin/testcommit4693
4107 = [up to date] testcommit4694 -> origin/testcommit4694
4108 = [up to date] testcommit4695 -> origin/testcommit4695
4109 = [up to date] testcommit4696 -> origin/testcommit4696
4110 = [up to date] testcommit4697 -> origin/testcommit4697
4111 = [up to date] testcommit4698 -> origin/testcommit4698
4112 = [up to date] testcommit4699 -> origin/testcommit4699
4113 = [up to date] testcommit47 -> origin/testcommit47
4114 = [up to date] testcommit470 -> origin/testcommit470
4115 = [up to date] testcommit4700 -> origin/testcommit4700
4116 = [up to date] testcommit4701 -> origin/testcommit4701
4117 = [up to date] testcommit4702 -> origin/testcommit4702
4118 = [up to date] testcommit4703 -> origin/testcommit4703
4119 = [up to date] testcommit4704 -> origin/testcommit4704
4120 = [up to date] testcommit4705 -> origin/testcommit4705
4121 = [up to date] testcommit4706 -> origin/testcommit4706
4122 = [up to date] testcommit4707 -> origin/testcommit4707
4123 = [up to date] testcommit4708 -> origin/testcommit4708
4124 = [up to date] testcommit4709 -> origin/testcommit4709
4125 = [up to date] testcommit471 -> origin/testcommit471
4126 = [up to date] testcommit4710 -> origin/testcommit4710
4127 = [up to date] testcommit4711 -> origin/testcommit4711
4128 = [up to date] testcommit4712 -> origin/testcommit4712
4129 = [up to date] testcommit4713 -> origin/testcommit4713
4130 = [up to date] testcommit4714 -> origin/testcommit4714
4131 = [up to date] testcommit4715 -> origin/testcommit4715
4132 = [up to date] testcommit4716 -> origin/testcommit4716
4133 = [up to date] testcommit4717 -> origin/testcommit4717
4134 = [up to date] testcommit4718 -> origin/testcommit4718
4135 = [up to date] testcommit4719 -> origin/testcommit4719
4136 = [up to date] testcommit472 -> origin/testcommit472
4137 = [up to date] testcommit4720 -> origin/testcommit4720
4138 = [up to date] testcommit4721 -> origin/testcommit4721
4139 = [up to date] testcommit4722 -> origin/testcommit4722
4140 = [up to date] testcommit4723 -> origin/testcommit4723
4141 = [up to date] testcommit4724 -> origin/testcommit4724
4142 = [up to date] testcommit4725 -> origin/testcommit4725
4143 = [up to date] testcommit4726 -> origin/testcommit4726
4144 = [up to date] testcommit4727 -> origin/testcommit4727
4145 = [up to date] testcommit4728 -> origin/testcommit4728
4146 = [up to date] testcommit4729 -> origin/testcommit4729
4147 = [up to date] testcommit473 -> origin/testcommit473
4148 = [up to date] testcommit4730 -> origin/testcommit4730
4149 = [up to date] testcommit4731 -> origin/testcommit4731
4150 = [up to date] testcommit4732 -> origin/testcommit4732
4151 = [up to date] testcommit4733 -> origin/testcommit4733
4152 = [up to date] testcommit4734 -> origin/testcommit4734
4153 = [up to date] testcommit4735 -> origin/testcommit4735
4154 = [up to date] testcommit4736 -> origin/testcommit4736
4155 = [up to date] testcommit4737 -> origin/testcommit4737
4156 = [up to date] testcommit4738 -> origin/testcommit4738
4157 = [up to date] testcommit4739 -> origin/testcommit4739
4158 = [up to date] testcommit474 -> origin/testcommit474
4159 = [up to date] testcommit4740 -> origin/testcommit4740
4160 = [up to date] testcommit4741 -> origin/testcommit4741
4161 = [up to date] testcommit4742 -> origin/testcommit4742
4162 = [up to date] testcommit4743 -> origin/testcommit4743
4163 = [up to date] testcommit4744 -> origin/testcommit4744
4164 = [up to date] testcommit4745 -> origin/testcommit4745
4165 = [up to date] testcommit4746 -> origin/testcommit4746
4166 = [up to date] testcommit4747 -> origin/testcommit4747
4167 = [up to date] testcommit4748 -> origin/testcommit4748
4168 = [up to date] testcommit4749 -> origin/testcommit4749
4169 = [up to date] testcommit475 -> origin/testcommit475
4170 = [up to date] testcommit4750 -> origin/testcommit4750
4171 = [up to date] testcommit4751 -> origin/testcommit4751
4172 = [up to date] testcommit4752 -> origin/testcommit4752
4173 = [up to date] testcommit4753 -> origin/testcommit4753
4174 = [up to date] testcommit4754 -> origin/testcommit4754
4175 = [up to date] testcommit4755 -> origin/testcommit4755
4176 = [up to date] testcommit4756 -> origin/testcommit4756
4177 = [up to date] testcommit4757 -> origin/testcommit4757
4178 = [up to date] testcommit4758 -> origin/testcommit4758
4179 = [up to date] testcommit4759 -> origin/testcommit4759
4180 = [up to date] testcommit476 -> origin/testcommit476
4181 = [up to date] testcommit4760 -> origin/testcommit4760
4182 = [up to date] testcommit4761 -> origin/testcommit4761
4183 = [up to date] testcommit4762 -> origin/testcommit4762
4184 = [up to date] testcommit4763 -> origin/testcommit4763
4185 = [up to date] testcommit4764 -> origin/testcommit4764
4186 = [up to date] testcommit4765 -> origin/testcommit4765
4187 = [up to date] testcommit4766 -> origin/testcommit4766
4188 = [up to date] testcommit4767 -> origin/testcommit4767
4189 = [up to date] testcommit4768 -> origin/testcommit4768
4190 = [up to date] testcommit4769 -> origin/testcommit4769
4191 = [up to date] testcommit477 -> origin/testcommit477
4192 = [up to date] testcommit4770 -> origin/testcommit4770
4193 = [up to date] testcommit4771 -> origin/testcommit4771
4194 = [up to date] testcommit4772 -> origin/testcommit4772
4195 = [up to date] testcommit4773 -> origin/testcommit4773
4196 = [up to date] testcommit4774 -> origin/testcommit4774
4197 = [up to date] testcommit4775 -> origin/testcommit4775
4198 = [up to date] testcommit4776 -> origin/testcommit4776
4199 = [up to date] testcommit4777 -> origin/testcommit4777
4200 = [up to date] testcommit4778 -> origin/testcommit4778
4201 = [up to date] testcommit4779 -> origin/testcommit4779
4202 = [up to date] testcommit478 -> origin/testcommit478
4203 = [up to date] testcommit4780 -> origin/testcommit4780
4204 = [up to date] testcommit4781 -> origin/testcommit4781
4205 = [up to date] testcommit4782 -> origin/testcommit4782
4206 = [up to date] testcommit4783 -> origin/testcommit4783
4207 = [up to date] testcommit4784 -> origin/testcommit4784
4208 = [up to date] testcommit4785 -> origin/testcommit4785
4209 = [up to date] testcommit4786 -> origin/testcommit4786
4210 = [up to date] testcommit4787 -> origin/testcommit4787
4211 = [up to date] testcommit4788 -> origin/testcommit4788
4212 = [up to date] testcommit4789 -> origin/testcommit4789
4213 = [up to date] testcommit479 -> origin/testcommit479
4214 = [up to date] testcommit4790 -> origin/testcommit4790
4215 = [up to date] testcommit4791 -> origin/testcommit4791
4216 = [up to date] testcommit4792 -> origin/testcommit4792
4217 = [up to date] testcommit4793 -> origin/testcommit4793
4218 = [up to date] testcommit4794 -> origin/testcommit4794
4219 = [up to date] testcommit4795 -> origin/testcommit4795
4220 = [up to date] testcommit4796 -> origin/testcommit4796
4221 = [up to date] testcommit4797 -> origin/testcommit4797
4222 = [up to date] testcommit4798 -> origin/testcommit4798
4223 = [up to date] testcommit4799 -> origin/testcommit4799
4224 = [up to date] testcommit48 -> origin/testcommit48
4225 = [up to date] testcommit480 -> origin/testcommit480
4226 = [up to date] testcommit4800 -> origin/testcommit4800
4227 = [up to date] testcommit4801 -> origin/testcommit4801
4228 = [up to date] testcommit4802 -> origin/testcommit4802
4229 = [up to date] testcommit4803 -> origin/testcommit4803
4230 = [up to date] testcommit4804 -> origin/testcommit4804
4231 = [up to date] testcommit4805 -> origin/testcommit4805
4232 = [up to date] testcommit4806 -> origin/testcommit4806
4233 = [up to date] testcommit4807 -> origin/testcommit4807
4234 = [up to date] testcommit4808 -> origin/testcommit4808
4235 = [up to date] testcommit4809 -> origin/testcommit4809
4236 = [up to date] testcommit481 -> origin/testcommit481
4237 = [up to date] testcommit4810 -> origin/testcommit4810
4238 = [up to date] testcommit4811 -> origin/testcommit4811
4239 = [up to date] testcommit4812 -> origin/testcommit4812
4240 = [up to date] testcommit4813 -> origin/testcommit4813
4241 = [up to date] testcommit4814 -> origin/testcommit4814
4242 = [up to date] testcommit4815 -> origin/testcommit4815
4243 = [up to date] testcommit4816 -> origin/testcommit4816
4244 = [up to date] testcommit4817 -> origin/testcommit4817
4245 = [up to date] testcommit4818 -> origin/testcommit4818
4246 = [up to date] testcommit4819 -> origin/testcommit4819
4247 = [up to date] testcommit482 -> origin/testcommit482
4248 = [up to date] testcommit4820 -> origin/testcommit4820
4249 = [up to date] testcommit4821 -> origin/testcommit4821
4250 = [up to date] testcommit4822 -> origin/testcommit4822
4251 = [up to date] testcommit4823 -> origin/testcommit4823
4252 = [up to date] testcommit4824 -> origin/testcommit4824
4253 = [up to date] testcommit4825 -> origin/testcommit4825
4254 = [up to date] testcommit4826 -> origin/testcommit4826
4255 = [up to date] testcommit4827 -> origin/testcommit4827
4256 = [up to date] testcommit4828 -> origin/testcommit4828
4257 = [up to date] testcommit4829 -> origin/testcommit4829
4258 = [up to date] testcommit483 -> origin/testcommit483
4259 = [up to date] testcommit4830 -> origin/testcommit4830
4260 = [up to date] testcommit4831 -> origin/testcommit4831
4261 = [up to date] testcommit4832 -> origin/testcommit4832
4262 = [up to date] testcommit4833 -> origin/testcommit4833
4263 = [up to date] testcommit4834 -> origin/testcommit4834
4264 = [up to date] testcommit4835 -> origin/testcommit4835
4265 = [up to date] testcommit4836 -> origin/testcommit4836
4266 = [up to date] testcommit4837 -> origin/testcommit4837
4267 = [up to date] testcommit4838 -> origin/testcommit4838
4268 = [up to date] testcommit4839 -> origin/testcommit4839
4269 = [up to date] testcommit484 -> origin/testcommit484
4270 = [up to date] testcommit4840 -> origin/testcommit4840
4271 = [up to date] testcommit4841 -> origin/testcommit4841
4272 = [up to date] testcommit4842 -> origin/testcommit4842
4273 = [up to date] testcommit4843 -> origin/testcommit4843
4274 = [up to date] testcommit4844 -> origin/testcommit4844
4275 = [up to date] testcommit4845 -> origin/testcommit4845
4276 = [up to date] testcommit4846 -> origin/testcommit4846
4277 = [up to date] testcommit4847 -> origin/testcommit4847
4278 = [up to date] testcommit4848 -> origin/testcommit4848
4279 = [up to date] testcommit4849 -> origin/testcommit4849
4280 = [up to date] testcommit485 -> origin/testcommit485
4281 = [up to date] testcommit4850 -> origin/testcommit4850
4282 = [up to date] testcommit4851 -> origin/testcommit4851
4283 = [up to date] testcommit4852 -> origin/testcommit4852
4284 = [up to date] testcommit4853 -> origin/testcommit4853
4285 = [up to date] testcommit4854 -> origin/testcommit4854
4286 = [up to date] testcommit4855 -> origin/testcommit4855
4287 = [up to date] testcommit4856 -> origin/testcommit4856
4288 = [up to date] testcommit4857 -> origin/testcommit4857
4289 = [up to date] testcommit4858 -> origin/testcommit4858
4290 = [up to date] testcommit4859 -> origin/testcommit4859
4291 = [up to date] testcommit486 -> origin/testcommit486
4292 = [up to date] testcommit4860 -> origin/testcommit4860
4293 = [up to date] testcommit4861 -> origin/testcommit4861
4294 = [up to date] testcommit4862 -> origin/testcommit4862
4295 = [up to date] testcommit4863 -> origin/testcommit4863
4296 = [up to date] testcommit4864 -> origin/testcommit4864
4297 = [up to date] testcommit4865 -> origin/testcommit4865
4298 = [up to date] testcommit4866 -> origin/testcommit4866
4299 = [up to date] testcommit4867 -> origin/testcommit4867
4300 = [up to date] testcommit4868 -> origin/testcommit4868
4301 = [up to date] testcommit4869 -> origin/testcommit4869
4302 = [up to date] testcommit487 -> origin/testcommit487
4303 = [up to date] testcommit4870 -> origin/testcommit4870
4304 = [up to date] testcommit4871 -> origin/testcommit4871
4305 = [up to date] testcommit4872 -> origin/testcommit4872
4306 = [up to date] testcommit4873 -> origin/testcommit4873
4307 = [up to date] testcommit4874 -> origin/testcommit4874
4308 = [up to date] testcommit4875 -> origin/testcommit4875
4309 = [up to date] testcommit4876 -> origin/testcommit4876
4310 = [up to date] testcommit4877 -> origin/testcommit4877
4311 = [up to date] testcommit4878 -> origin/testcommit4878
4312 = [up to date] testcommit4879 -> origin/testcommit4879
4313 = [up to date] testcommit488 -> origin/testcommit488
4314 = [up to date] testcommit4880 -> origin/testcommit4880
4315 = [up to date] testcommit4881 -> origin/testcommit4881
4316 = [up to date] testcommit4882 -> origin/testcommit4882
4317 = [up to date] testcommit4883 -> origin/testcommit4883
4318 = [up to date] testcommit4884 -> origin/testcommit4884
4319 = [up to date] testcommit4885 -> origin/testcommit4885
4320 = [up to date] testcommit4886 -> origin/testcommit4886
4321 = [up to date] testcommit4887 -> origin/testcommit4887
4322 = [up to date] testcommit4888 -> origin/testcommit4888
4323 = [up to date] testcommit4889 -> origin/testcommit4889
4324 = [up to date] testcommit489 -> origin/testcommit489
4325 = [up to date] testcommit4890 -> origin/testcommit4890
4326 = [up to date] testcommit4891 -> origin/testcommit4891
4327 = [up to date] testcommit4892 -> origin/testcommit4892
4328 = [up to date] testcommit4893 -> origin/testcommit4893
4329 = [up to date] testcommit4894 -> origin/testcommit4894
4330 = [up to date] testcommit4895 -> origin/testcommit4895
4331 = [up to date] testcommit4896 -> origin/testcommit4896
4332 = [up to date] testcommit4897 -> origin/testcommit4897
4333 = [up to date] testcommit4898 -> origin/testcommit4898
4334 = [up to date] testcommit4899 -> origin/testcommit4899
4335 = [up to date] testcommit49 -> origin/testcommit49
4336 = [up to date] testcommit490 -> origin/testcommit490
4337 = [up to date] testcommit4900 -> origin/testcommit4900
4338 = [up to date] testcommit4901 -> origin/testcommit4901
4339 = [up to date] testcommit4902 -> origin/testcommit4902
4340 = [up to date] testcommit4903 -> origin/testcommit4903
4341 = [up to date] testcommit4904 -> origin/testcommit4904
4342 = [up to date] testcommit4905 -> origin/testcommit4905
4343 = [up to date] testcommit4906 -> origin/testcommit4906
4344 = [up to date] testcommit4907 -> origin/testcommit4907
4345 = [up to date] testcommit4908 -> origin/testcommit4908
4346 = [up to date] testcommit4909 -> origin/testcommit4909
4347 = [up to date] testcommit491 -> origin/testcommit491
4348 = [up to date] testcommit4910 -> origin/testcommit4910
4349 = [up to date] testcommit4911 -> origin/testcommit4911
4350 = [up to date] testcommit4912 -> origin/testcommit4912
4351 = [up to date] testcommit4913 -> origin/testcommit4913
4352 = [up to date] testcommit4914 -> origin/testcommit4914
4353 = [up to date] testcommit4915 -> origin/testcommit4915
4354 = [up to date] testcommit4916 -> origin/testcommit4916
4355 = [up to date] testcommit4917 -> origin/testcommit4917
4356 = [up to date] testcommit4918 -> origin/testcommit4918
4357 = [up to date] testcommit4919 -> origin/testcommit4919
4358 = [up to date] testcommit492 -> origin/testcommit492
4359 = [up to date] testcommit4920 -> origin/testcommit4920
4360 = [up to date] testcommit4921 -> origin/testcommit4921
4361 = [up to date] testcommit4922 -> origin/testcommit4922
4362 = [up to date] testcommit4923 -> origin/testcommit4923
4363 = [up to date] testcommit4924 -> origin/testcommit4924
4364 = [up to date] testcommit4925 -> origin/testcommit4925
4365 = [up to date] testcommit4926 -> origin/testcommit4926
4366 = [up to date] testcommit4927 -> origin/testcommit4927
4367 = [up to date] testcommit4928 -> origin/testcommit4928
4368 = [up to date] testcommit4929 -> origin/testcommit4929
4369 = [up to date] testcommit493 -> origin/testcommit493
4370 = [up to date] testcommit4930 -> origin/testcommit4930
4371 = [up to date] testcommit4931 -> origin/testcommit4931
4372 = [up to date] testcommit4932 -> origin/testcommit4932
4373 = [up to date] testcommit4933 -> origin/testcommit4933
4374 = [up to date] testcommit4934 -> origin/testcommit4934
4375 = [up to date] testcommit4935 -> origin/testcommit4935
4376 = [up to date] testcommit4936 -> origin/testcommit4936
4377 = [up to date] testcommit4937 -> origin/testcommit4937
4378 = [up to date] testcommit4938 -> origin/testcommit4938
4379 = [up to date] testcommit4939 -> origin/testcommit4939
4380 = [up to date] testcommit494 -> origin/testcommit494
4381 = [up to date] testcommit4940 -> origin/testcommit4940
4382 = [up to date] testcommit4941 -> origin/testcommit4941
4383 = [up to date] testcommit4942 -> origin/testcommit4942
4384 = [up to date] testcommit4943 -> origin/testcommit4943
4385 = [up to date] testcommit4944 -> origin/testcommit4944
4386 = [up to date] testcommit4945 -> origin/testcommit4945
4387 = [up to date] testcommit4946 -> origin/testcommit4946
4388 = [up to date] testcommit4947 -> origin/testcommit4947
4389 = [up to date] testcommit4948 -> origin/testcommit4948
4390 = [up to date] testcommit4949 -> origin/testcommit4949
4391 = [up to date] testcommit495 -> origin/testcommit495
4392 = [up to date] testcommit4950 -> origin/testcommit4950
4393 = [up to date] testcommit4951 -> origin/testcommit4951
4394 = [up to date] testcommit4952 -> origin/testcommit4952
4395 = [up to date] testcommit4953 -> origin/testcommit4953
4396 = [up to date] testcommit4954 -> origin/testcommit4954
4397 = [up to date] testcommit4955 -> origin/testcommit4955
4398 = [up to date] testcommit4956 -> origin/testcommit4956
4399 = [up to date] testcommit4957 -> origin/testcommit4957
4400 = [up to date] testcommit4958 -> origin/testcommit4958
4401 = [up to date] testcommit4959 -> origin/testcommit4959
4402 = [up to date] testcommit496 -> origin/testcommit496
4403 = [up to date] testcommit4960 -> origin/testcommit4960
4404 = [up to date] testcommit4961 -> origin/testcommit4961
4405 = [up to date] testcommit4962 -> origin/testcommit4962
4406 = [up to date] testcommit4963 -> origin/testcommit4963
4407 = [up to date] testcommit4964 -> origin/testcommit4964
4408 = [up to date] testcommit4965 -> origin/testcommit4965
4409 = [up to date] testcommit4966 -> origin/testcommit4966
4410 = [up to date] testcommit4967 -> origin/testcommit4967
4411 = [up to date] testcommit4968 -> origin/testcommit4968
4412 = [up to date] testcommit4969 -> origin/testcommit4969
4413 = [up to date] testcommit497 -> origin/testcommit497
4414 = [up to date] testcommit4970 -> origin/testcommit4970
4415 = [up to date] testcommit4971 -> origin/testcommit4971
4416 = [up to date] testcommit4972 -> origin/testcommit4972
4417 = [up to date] testcommit4973 -> origin/testcommit4973
4418 = [up to date] testcommit4974 -> origin/testcommit4974
4419 = [up to date] testcommit4975 -> origin/testcommit4975
4420 = [up to date] testcommit4976 -> origin/testcommit4976
4421 = [up to date] testcommit4977 -> origin/testcommit4977
4422 = [up to date] testcommit4978 -> origin/testcommit4978
4423 = [up to date] testcommit4979 -> origin/testcommit4979
4424 = [up to date] testcommit498 -> origin/testcommit498
4425 = [up to date] testcommit4980 -> origin/testcommit4980
4426 = [up to date] testcommit4981 -> origin/testcommit4981
4427 = [up to date] testcommit4982 -> origin/testcommit4982
4428 = [up to date] testcommit4983 -> origin/testcommit4983
4429 = [up to date] testcommit4984 -> origin/testcommit4984
4430 = [up to date] testcommit4985 -> origin/testcommit4985
4431 = [up to date] testcommit4986 -> origin/testcommit4986
4432 = [up to date] testcommit4987 -> origin/testcommit4987
4433 = [up to date] testcommit4988 -> origin/testcommit4988
4434 = [up to date] testcommit4989 -> origin/testcommit4989
4435 = [up to date] testcommit499 -> origin/testcommit499
4436 = [up to date] testcommit4990 -> origin/testcommit4990
4437 = [up to date] testcommit4991 -> origin/testcommit4991
4438 = [up to date] testcommit4992 -> origin/testcommit4992
4439 = [up to date] testcommit4993 -> origin/testcommit4993
4440 = [up to date] testcommit4994 -> origin/testcommit4994
4441 = [up to date] testcommit4995 -> origin/testcommit4995
4442 = [up to date] testcommit4996 -> origin/testcommit4996
4443 = [up to date] testcommit4997 -> origin/testcommit4997
4444 = [up to date] testcommit4998 -> origin/testcommit4998
4445 = [up to date] testcommit4999 -> origin/testcommit4999
4446 = [up to date] testcommit5 -> origin/testcommit5
4447 = [up to date] testcommit50 -> origin/testcommit50
4448 = [up to date] testcommit500 -> origin/testcommit500
4449 = [up to date] testcommit5000 -> origin/testcommit5000
4450 = [up to date] testcommit501 -> origin/testcommit501
4451 = [up to date] testcommit502 -> origin/testcommit502
4452 = [up to date] testcommit503 -> origin/testcommit503
4453 = [up to date] testcommit504 -> origin/testcommit504
4454 = [up to date] testcommit505 -> origin/testcommit505
4455 = [up to date] testcommit506 -> origin/testcommit506
4456 = [up to date] testcommit507 -> origin/testcommit507
4457 = [up to date] testcommit508 -> origin/testcommit508
4458 = [up to date] testcommit509 -> origin/testcommit509
4459 = [up to date] testcommit51 -> origin/testcommit51
4460 = [up to date] testcommit510 -> origin/testcommit510
4461 = [up to date] testcommit511 -> origin/testcommit511
4462 = [up to date] testcommit512 -> origin/testcommit512
4463 = [up to date] testcommit513 -> origin/testcommit513
4464 = [up to date] testcommit514 -> origin/testcommit514
4465 = [up to date] testcommit515 -> origin/testcommit515
4466 = [up to date] testcommit516 -> origin/testcommit516
4467 = [up to date] testcommit517 -> origin/testcommit517
4468 = [up to date] testcommit518 -> origin/testcommit518
4469 = [up to date] testcommit519 -> origin/testcommit519
4470 = [up to date] testcommit52 -> origin/testcommit52
4471 = [up to date] testcommit520 -> origin/testcommit520
4472 = [up to date] testcommit521 -> origin/testcommit521
4473 = [up to date] testcommit522 -> origin/testcommit522
4474 = [up to date] testcommit523 -> origin/testcommit523
4475 = [up to date] testcommit524 -> origin/testcommit524
4476 = [up to date] testcommit525 -> origin/testcommit525
4477 = [up to date] testcommit526 -> origin/testcommit526
4478 = [up to date] testcommit527 -> origin/testcommit527
4479 = [up to date] testcommit528 -> origin/testcommit528
4480 = [up to date] testcommit529 -> origin/testcommit529
4481 = [up to date] testcommit53 -> origin/testcommit53
4482 = [up to date] testcommit530 -> origin/testcommit530
4483 = [up to date] testcommit531 -> origin/testcommit531
4484 = [up to date] testcommit532 -> origin/testcommit532
4485 = [up to date] testcommit533 -> origin/testcommit533
4486 = [up to date] testcommit534 -> origin/testcommit534
4487 = [up to date] testcommit535 -> origin/testcommit535
4488 = [up to date] testcommit536 -> origin/testcommit536
4489 = [up to date] testcommit537 -> origin/testcommit537
4490 = [up to date] testcommit538 -> origin/testcommit538
4491 = [up to date] testcommit539 -> origin/testcommit539
4492 = [up to date] testcommit54 -> origin/testcommit54
4493 = [up to date] testcommit540 -> origin/testcommit540
4494 = [up to date] testcommit541 -> origin/testcommit541
4495 = [up to date] testcommit542 -> origin/testcommit542
4496 = [up to date] testcommit543 -> origin/testcommit543
4497 = [up to date] testcommit544 -> origin/testcommit544
4498 = [up to date] testcommit545 -> origin/testcommit545
4499 = [up to date] testcommit546 -> origin/testcommit546
4500 = [up to date] testcommit547 -> origin/testcommit547
4501 = [up to date] testcommit548 -> origin/testcommit548
4502 = [up to date] testcommit549 -> origin/testcommit549
4503 = [up to date] testcommit55 -> origin/testcommit55
4504 = [up to date] testcommit550 -> origin/testcommit550
4505 = [up to date] testcommit551 -> origin/testcommit551
4506 = [up to date] testcommit552 -> origin/testcommit552
4507 = [up to date] testcommit553 -> origin/testcommit553
4508 = [up to date] testcommit554 -> origin/testcommit554
4509 = [up to date] testcommit555 -> origin/testcommit555
4510 = [up to date] testcommit556 -> origin/testcommit556
4511 = [up to date] testcommit557 -> origin/testcommit557
4512 = [up to date] testcommit558 -> origin/testcommit558
4513 = [up to date] testcommit559 -> origin/testcommit559
4514 = [up to date] testcommit56 -> origin/testcommit56
4515 = [up to date] testcommit560 -> origin/testcommit560
4516 = [up to date] testcommit561 -> origin/testcommit561
4517 = [up to date] testcommit562 -> origin/testcommit562
4518 = [up to date] testcommit563 -> origin/testcommit563
4519 = [up to date] testcommit564 -> origin/testcommit564
4520 = [up to date] testcommit565 -> origin/testcommit565
4521 = [up to date] testcommit566 -> origin/testcommit566
4522 = [up to date] testcommit567 -> origin/testcommit567
4523 = [up to date] testcommit568 -> origin/testcommit568
4524 = [up to date] testcommit569 -> origin/testcommit569
4525 = [up to date] testcommit57 -> origin/testcommit57
4526 = [up to date] testcommit570 -> origin/testcommit570
4527 = [up to date] testcommit571 -> origin/testcommit571
4528 = [up to date] testcommit572 -> origin/testcommit572
4529 = [up to date] testcommit573 -> origin/testcommit573
4530 = [up to date] testcommit574 -> origin/testcommit574
4531 = [up to date] testcommit575 -> origin/testcommit575
4532 = [up to date] testcommit576 -> origin/testcommit576
4533 = [up to date] testcommit577 -> origin/testcommit577
4534 = [up to date] testcommit578 -> origin/testcommit578
4535 = [up to date] testcommit579 -> origin/testcommit579
4536 = [up to date] testcommit58 -> origin/testcommit58
4537 = [up to date] testcommit580 -> origin/testcommit580
4538 = [up to date] testcommit581 -> origin/testcommit581
4539 = [up to date] testcommit582 -> origin/testcommit582
4540 = [up to date] testcommit583 -> origin/testcommit583
4541 = [up to date] testcommit584 -> origin/testcommit584
4542 = [up to date] testcommit585 -> origin/testcommit585
4543 = [up to date] testcommit586 -> origin/testcommit586
4544 = [up to date] testcommit587 -> origin/testcommit587
4545 = [up to date] testcommit588 -> origin/testcommit588
4546 = [up to date] testcommit589 -> origin/testcommit589
4547 = [up to date] testcommit59 -> origin/testcommit59
4548 = [up to date] testcommit590 -> origin/testcommit590
4549 = [up to date] testcommit591 -> origin/testcommit591
4550 = [up to date] testcommit592 -> origin/testcommit592
4551 = [up to date] testcommit593 -> origin/testcommit593
4552 = [up to date] testcommit594 -> origin/testcommit594
4553 = [up to date] testcommit595 -> origin/testcommit595
4554 = [up to date] testcommit596 -> origin/testcommit596
4555 = [up to date] testcommit597 -> origin/testcommit597
4556 = [up to date] testcommit598 -> origin/testcommit598
4557 = [up to date] testcommit599 -> origin/testcommit599
4558 = [up to date] testcommit6 -> origin/testcommit6
4559 = [up to date] testcommit60 -> origin/testcommit60
4560 = [up to date] testcommit600 -> origin/testcommit600
4561 = [up to date] testcommit601 -> origin/testcommit601
4562 = [up to date] testcommit602 -> origin/testcommit602
4563 = [up to date] testcommit603 -> origin/testcommit603
4564 = [up to date] testcommit604 -> origin/testcommit604
4565 = [up to date] testcommit605 -> origin/testcommit605
4566 = [up to date] testcommit606 -> origin/testcommit606
4567 = [up to date] testcommit607 -> origin/testcommit607
4568 = [up to date] testcommit608 -> origin/testcommit608
4569 = [up to date] testcommit609 -> origin/testcommit609
4570 = [up to date] testcommit61 -> origin/testcommit61
4571 = [up to date] testcommit610 -> origin/testcommit610
4572 = [up to date] testcommit611 -> origin/testcommit611
4573 = [up to date] testcommit612 -> origin/testcommit612
4574 = [up to date] testcommit613 -> origin/testcommit613
4575 = [up to date] testcommit614 -> origin/testcommit614
4576 = [up to date] testcommit615 -> origin/testcommit615
4577 = [up to date] testcommit616 -> origin/testcommit616
4578 = [up to date] testcommit617 -> origin/testcommit617
4579 = [up to date] testcommit618 -> origin/testcommit618
4580 = [up to date] testcommit619 -> origin/testcommit619
4581 = [up to date] testcommit62 -> origin/testcommit62
4582 = [up to date] testcommit620 -> origin/testcommit620
4583 = [up to date] testcommit621 -> origin/testcommit621
4584 = [up to date] testcommit622 -> origin/testcommit622
4585 = [up to date] testcommit623 -> origin/testcommit623
4586 = [up to date] testcommit624 -> origin/testcommit624
4587 = [up to date] testcommit625 -> origin/testcommit625
4588 = [up to date] testcommit626 -> origin/testcommit626
4589 = [up to date] testcommit627 -> origin/testcommit627
4590 = [up to date] testcommit628 -> origin/testcommit628
4591 = [up to date] testcommit629 -> origin/testcommit629
4592 = [up to date] testcommit63 -> origin/testcommit63
4593 = [up to date] testcommit630 -> origin/testcommit630
4594 = [up to date] testcommit631 -> origin/testcommit631
4595 = [up to date] testcommit632 -> origin/testcommit632
4596 = [up to date] testcommit633 -> origin/testcommit633
4597 = [up to date] testcommit634 -> origin/testcommit634
4598 = [up to date] testcommit635 -> origin/testcommit635
4599 = [up to date] testcommit636 -> origin/testcommit636
4600 = [up to date] testcommit637 -> origin/testcommit637
4601 = [up to date] testcommit638 -> origin/testcommit638
4602 = [up to date] testcommit639 -> origin/testcommit639
4603 = [up to date] testcommit64 -> origin/testcommit64
4604 = [up to date] testcommit640 -> origin/testcommit640
4605 = [up to date] testcommit641 -> origin/testcommit641
4606 = [up to date] testcommit642 -> origin/testcommit642
4607 = [up to date] testcommit643 -> origin/testcommit643
4608 = [up to date] testcommit644 -> origin/testcommit644
4609 = [up to date] testcommit645 -> origin/testcommit645
4610 = [up to date] testcommit646 -> origin/testcommit646
4611 = [up to date] testcommit647 -> origin/testcommit647
4612 = [up to date] testcommit648 -> origin/testcommit648
4613 = [up to date] testcommit649 -> origin/testcommit649
4614 = [up to date] testcommit65 -> origin/testcommit65
4615 = [up to date] testcommit650 -> origin/testcommit650
4616 = [up to date] testcommit651 -> origin/testcommit651
4617 = [up to date] testcommit652 -> origin/testcommit652
4618 = [up to date] testcommit653 -> origin/testcommit653
4619 = [up to date] testcommit654 -> origin/testcommit654
4620 = [up to date] testcommit655 -> origin/testcommit655
4621 = [up to date] testcommit656 -> origin/testcommit656
4622 = [up to date] testcommit657 -> origin/testcommit657
4623 = [up to date] testcommit658 -> origin/testcommit658
4624 = [up to date] testcommit659 -> origin/testcommit659
4625 = [up to date] testcommit66 -> origin/testcommit66
4626 = [up to date] testcommit660 -> origin/testcommit660
4627 = [up to date] testcommit661 -> origin/testcommit661
4628 = [up to date] testcommit662 -> origin/testcommit662
4629 = [up to date] testcommit663 -> origin/testcommit663
4630 = [up to date] testcommit664 -> origin/testcommit664
4631 = [up to date] testcommit665 -> origin/testcommit665
4632 = [up to date] testcommit666 -> origin/testcommit666
4633 = [up to date] testcommit667 -> origin/testcommit667
4634 = [up to date] testcommit668 -> origin/testcommit668
4635 = [up to date] testcommit669 -> origin/testcommit669
4636 = [up to date] testcommit67 -> origin/testcommit67
4637 = [up to date] testcommit670 -> origin/testcommit670
4638 = [up to date] testcommit671 -> origin/testcommit671
4639 = [up to date] testcommit672 -> origin/testcommit672
4640 = [up to date] testcommit673 -> origin/testcommit673
4641 = [up to date] testcommit674 -> origin/testcommit674
4642 = [up to date] testcommit675 -> origin/testcommit675
4643 = [up to date] testcommit676 -> origin/testcommit676
4644 = [up to date] testcommit677 -> origin/testcommit677
4645 = [up to date] testcommit678 -> origin/testcommit678
4646 = [up to date] testcommit679 -> origin/testcommit679
4647 = [up to date] testcommit68 -> origin/testcommit68
4648 = [up to date] testcommit680 -> origin/testcommit680
4649 = [up to date] testcommit681 -> origin/testcommit681
4650 = [up to date] testcommit682 -> origin/testcommit682
4651 = [up to date] testcommit683 -> origin/testcommit683
4652 = [up to date] testcommit684 -> origin/testcommit684
4653 = [up to date] testcommit685 -> origin/testcommit685
4654 = [up to date] testcommit686 -> origin/testcommit686
4655 = [up to date] testcommit687 -> origin/testcommit687
4656 = [up to date] testcommit688 -> origin/testcommit688
4657 = [up to date] testcommit689 -> origin/testcommit689
4658 = [up to date] testcommit69 -> origin/testcommit69
4659 = [up to date] testcommit690 -> origin/testcommit690
4660 = [up to date] testcommit691 -> origin/testcommit691
4661 = [up to date] testcommit692 -> origin/testcommit692
4662 = [up to date] testcommit693 -> origin/testcommit693
4663 = [up to date] testcommit694 -> origin/testcommit694
4664 = [up to date] testcommit695 -> origin/testcommit695
4665 = [up to date] testcommit696 -> origin/testcommit696
4666 = [up to date] testcommit697 -> origin/testcommit697
4667 = [up to date] testcommit698 -> origin/testcommit698
4668 = [up to date] testcommit699 -> origin/testcommit699
4669 = [up to date] testcommit7 -> origin/testcommit7
4670 = [up to date] testcommit70 -> origin/testcommit70
4671 = [up to date] testcommit700 -> origin/testcommit700
4672 = [up to date] testcommit701 -> origin/testcommit701
4673 = [up to date] testcommit702 -> origin/testcommit702
4674 = [up to date] testcommit703 -> origin/testcommit703
4675 = [up to date] testcommit704 -> origin/testcommit704
4676 = [up to date] testcommit705 -> origin/testcommit705
4677 = [up to date] testcommit706 -> origin/testcommit706
4678 = [up to date] testcommit707 -> origin/testcommit707
4679 = [up to date] testcommit708 -> origin/testcommit708
4680 = [up to date] testcommit709 -> origin/testcommit709
4681 = [up to date] testcommit71 -> origin/testcommit71
4682 = [up to date] testcommit710 -> origin/testcommit710
4683 = [up to date] testcommit711 -> origin/testcommit711
4684 = [up to date] testcommit712 -> origin/testcommit712
4685 = [up to date] testcommit713 -> origin/testcommit713
4686 = [up to date] testcommit714 -> origin/testcommit714
4687 = [up to date] testcommit715 -> origin/testcommit715
4688 = [up to date] testcommit716 -> origin/testcommit716
4689 = [up to date] testcommit717 -> origin/testcommit717
4690 = [up to date] testcommit718 -> origin/testcommit718
4691 = [up to date] testcommit719 -> origin/testcommit719
4692 = [up to date] testcommit72 -> origin/testcommit72
4693 = [up to date] testcommit720 -> origin/testcommit720
4694 = [up to date] testcommit721 -> origin/testcommit721
4695 = [up to date] testcommit722 -> origin/testcommit722
4696 = [up to date] testcommit723 -> origin/testcommit723
4697 = [up to date] testcommit724 -> origin/testcommit724
4698 = [up to date] testcommit725 -> origin/testcommit725
4699 = [up to date] testcommit726 -> origin/testcommit726
4700 = [up to date] testcommit727 -> origin/testcommit727
4701 = [up to date] testcommit728 -> origin/testcommit728
4702 = [up to date] testcommit729 -> origin/testcommit729
4703 = [up to date] testcommit73 -> origin/testcommit73
4704 = [up to date] testcommit730 -> origin/testcommit730
4705 = [up to date] testcommit731 -> origin/testcommit731
4706 = [up to date] testcommit732 -> origin/testcommit732
4707 = [up to date] testcommit733 -> origin/testcommit733
4708 = [up to date] testcommit734 -> origin/testcommit734
4709 = [up to date] testcommit735 -> origin/testcommit735
4710 = [up to date] testcommit736 -> origin/testcommit736
4711 = [up to date] testcommit737 -> origin/testcommit737
4712 = [up to date] testcommit738 -> origin/testcommit738
4713 = [up to date] testcommit739 -> origin/testcommit739
4714 = [up to date] testcommit74 -> origin/testcommit74
4715 = [up to date] testcommit740 -> origin/testcommit740
4716 = [up to date] testcommit741 -> origin/testcommit741
4717 = [up to date] testcommit742 -> origin/testcommit742
4718 = [up to date] testcommit743 -> origin/testcommit743
4719 = [up to date] testcommit744 -> origin/testcommit744
4720 = [up to date] testcommit745 -> origin/testcommit745
4721 = [up to date] testcommit746 -> origin/testcommit746
4722 = [up to date] testcommit747 -> origin/testcommit747
4723 = [up to date] testcommit748 -> origin/testcommit748
4724 = [up to date] testcommit749 -> origin/testcommit749
4725 = [up to date] testcommit75 -> origin/testcommit75
4726 = [up to date] testcommit750 -> origin/testcommit750
4727 = [up to date] testcommit751 -> origin/testcommit751
4728 = [up to date] testcommit752 -> origin/testcommit752
4729 = [up to date] testcommit753 -> origin/testcommit753
4730 = [up to date] testcommit754 -> origin/testcommit754
4731 = [up to date] testcommit755 -> origin/testcommit755
4732 = [up to date] testcommit756 -> origin/testcommit756
4733 = [up to date] testcommit757 -> origin/testcommit757
4734 = [up to date] testcommit758 -> origin/testcommit758
4735 = [up to date] testcommit759 -> origin/testcommit759
4736 = [up to date] testcommit76 -> origin/testcommit76
4737 = [up to date] testcommit760 -> origin/testcommit760
4738 = [up to date] testcommit761 -> origin/testcommit761
4739 = [up to date] testcommit762 -> origin/testcommit762
4740 = [up to date] testcommit763 -> origin/testcommit763
4741 = [up to date] testcommit764 -> origin/testcommit764
4742 = [up to date] testcommit765 -> origin/testcommit765
4743 = [up to date] testcommit766 -> origin/testcommit766
4744 = [up to date] testcommit767 -> origin/testcommit767
4745 = [up to date] testcommit768 -> origin/testcommit768
4746 = [up to date] testcommit769 -> origin/testcommit769
4747 = [up to date] testcommit77 -> origin/testcommit77
4748 = [up to date] testcommit770 -> origin/testcommit770
4749 = [up to date] testcommit771 -> origin/testcommit771
4750 = [up to date] testcommit772 -> origin/testcommit772
4751 = [up to date] testcommit773 -> origin/testcommit773
4752 = [up to date] testcommit774 -> origin/testcommit774
4753 = [up to date] testcommit775 -> origin/testcommit775
4754 = [up to date] testcommit776 -> origin/testcommit776
4755 = [up to date] testcommit777 -> origin/testcommit777
4756 = [up to date] testcommit778 -> origin/testcommit778
4757 = [up to date] testcommit779 -> origin/testcommit779
4758 = [up to date] testcommit78 -> origin/testcommit78
4759 = [up to date] testcommit780 -> origin/testcommit780
4760 = [up to date] testcommit781 -> origin/testcommit781
4761 = [up to date] testcommit782 -> origin/testcommit782
4762 = [up to date] testcommit783 -> origin/testcommit783
4763 = [up to date] testcommit784 -> origin/testcommit784
4764 = [up to date] testcommit785 -> origin/testcommit785
4765 = [up to date] testcommit786 -> origin/testcommit786
4766 = [up to date] testcommit787 -> origin/testcommit787
4767 = [up to date] testcommit788 -> origin/testcommit788
4768 = [up to date] testcommit789 -> origin/testcommit789
4769 = [up to date] testcommit79 -> origin/testcommit79
4770 = [up to date] testcommit790 -> origin/testcommit790
4771 = [up to date] testcommit791 -> origin/testcommit791
4772 = [up to date] testcommit792 -> origin/testcommit792
4773 = [up to date] testcommit793 -> origin/testcommit793
4774 = [up to date] testcommit794 -> origin/testcommit794
4775 = [up to date] testcommit795 -> origin/testcommit795
4776 = [up to date] testcommit796 -> origin/testcommit796
4777 = [up to date] testcommit797 -> origin/testcommit797
4778 = [up to date] testcommit798 -> origin/testcommit798
4779 = [up to date] testcommit799 -> origin/testcommit799
4780 = [up to date] testcommit8 -> origin/testcommit8
4781 = [up to date] testcommit80 -> origin/testcommit80
4782 = [up to date] testcommit800 -> origin/testcommit800
4783 = [up to date] testcommit801 -> origin/testcommit801
4784 = [up to date] testcommit802 -> origin/testcommit802
4785 = [up to date] testcommit803 -> origin/testcommit803
4786 = [up to date] testcommit804 -> origin/testcommit804
4787 = [up to date] testcommit805 -> origin/testcommit805
4788 = [up to date] testcommit806 -> origin/testcommit806
4789 = [up to date] testcommit807 -> origin/testcommit807
4790 = [up to date] testcommit808 -> origin/testcommit808
4791 = [up to date] testcommit809 -> origin/testcommit809
4792 = [up to date] testcommit81 -> origin/testcommit81
4793 = [up to date] testcommit810 -> origin/testcommit810
4794 = [up to date] testcommit811 -> origin/testcommit811
4795 = [up to date] testcommit812 -> origin/testcommit812
4796 = [up to date] testcommit813 -> origin/testcommit813
4797 = [up to date] testcommit814 -> origin/testcommit814
4798 = [up to date] testcommit815 -> origin/testcommit815
4799 = [up to date] testcommit816 -> origin/testcommit816
4800 = [up to date] testcommit817 -> origin/testcommit817
4801 = [up to date] testcommit818 -> origin/testcommit818
4802 = [up to date] testcommit819 -> origin/testcommit819
4803 = [up to date] testcommit82 -> origin/testcommit82
4804 = [up to date] testcommit820 -> origin/testcommit820
4805 = [up to date] testcommit821 -> origin/testcommit821
4806 = [up to date] testcommit822 -> origin/testcommit822
4807 = [up to date] testcommit823 -> origin/testcommit823
4808 = [up to date] testcommit824 -> origin/testcommit824
4809 = [up to date] testcommit825 -> origin/testcommit825
4810 = [up to date] testcommit826 -> origin/testcommit826
4811 = [up to date] testcommit827 -> origin/testcommit827
4812 = [up to date] testcommit828 -> origin/testcommit828
4813 = [up to date] testcommit829 -> origin/testcommit829
4814 = [up to date] testcommit83 -> origin/testcommit83
4815 = [up to date] testcommit830 -> origin/testcommit830
4816 = [up to date] testcommit831 -> origin/testcommit831
4817 = [up to date] testcommit832 -> origin/testcommit832
4818 = [up to date] testcommit833 -> origin/testcommit833
4819 = [up to date] testcommit834 -> origin/testcommit834
4820 = [up to date] testcommit835 -> origin/testcommit835
4821 = [up to date] testcommit836 -> origin/testcommit836
4822 = [up to date] testcommit837 -> origin/testcommit837
4823 = [up to date] testcommit838 -> origin/testcommit838
4824 = [up to date] testcommit839 -> origin/testcommit839
4825 = [up to date] testcommit84 -> origin/testcommit84
4826 = [up to date] testcommit840 -> origin/testcommit840
4827 = [up to date] testcommit841 -> origin/testcommit841
4828 = [up to date] testcommit842 -> origin/testcommit842
4829 = [up to date] testcommit843 -> origin/testcommit843
4830 = [up to date] testcommit844 -> origin/testcommit844
4831 = [up to date] testcommit845 -> origin/testcommit845
4832 = [up to date] testcommit846 -> origin/testcommit846
4833 = [up to date] testcommit847 -> origin/testcommit847
4834 = [up to date] testcommit848 -> origin/testcommit848
4835 = [up to date] testcommit849 -> origin/testcommit849
4836 = [up to date] testcommit85 -> origin/testcommit85
4837 = [up to date] testcommit850 -> origin/testcommit850
4838 = [up to date] testcommit851 -> origin/testcommit851
4839 = [up to date] testcommit852 -> origin/testcommit852
4840 = [up to date] testcommit853 -> origin/testcommit853
4841 = [up to date] testcommit854 -> origin/testcommit854
4842 = [up to date] testcommit855 -> origin/testcommit855
4843 = [up to date] testcommit856 -> origin/testcommit856
4844 = [up to date] testcommit857 -> origin/testcommit857
4845 = [up to date] testcommit858 -> origin/testcommit858
4846 = [up to date] testcommit859 -> origin/testcommit859
4847 = [up to date] testcommit86 -> origin/testcommit86
4848 = [up to date] testcommit860 -> origin/testcommit860
4849 = [up to date] testcommit861 -> origin/testcommit861
4850 = [up to date] testcommit862 -> origin/testcommit862
4851 = [up to date] testcommit863 -> origin/testcommit863
4852 = [up to date] testcommit864 -> origin/testcommit864
4853 = [up to date] testcommit865 -> origin/testcommit865
4854 = [up to date] testcommit866 -> origin/testcommit866
4855 = [up to date] testcommit867 -> origin/testcommit867
4856 = [up to date] testcommit868 -> origin/testcommit868
4857 = [up to date] testcommit869 -> origin/testcommit869
4858 = [up to date] testcommit87 -> origin/testcommit87
4859 = [up to date] testcommit870 -> origin/testcommit870
4860 = [up to date] testcommit871 -> origin/testcommit871
4861 = [up to date] testcommit872 -> origin/testcommit872
4862 = [up to date] testcommit873 -> origin/testcommit873
4863 = [up to date] testcommit874 -> origin/testcommit874
4864 = [up to date] testcommit875 -> origin/testcommit875
4865 = [up to date] testcommit876 -> origin/testcommit876
4866 = [up to date] testcommit877 -> origin/testcommit877
4867 = [up to date] testcommit878 -> origin/testcommit878
4868 = [up to date] testcommit879 -> origin/testcommit879
4869 = [up to date] testcommit88 -> origin/testcommit88
4870 = [up to date] testcommit880 -> origin/testcommit880
4871 = [up to date] testcommit881 -> origin/testcommit881
4872 = [up to date] testcommit882 -> origin/testcommit882
4873 = [up to date] testcommit883 -> origin/testcommit883
4874 = [up to date] testcommit884 -> origin/testcommit884
4875 = [up to date] testcommit885 -> origin/testcommit885
4876 = [up to date] testcommit886 -> origin/testcommit886
4877 = [up to date] testcommit887 -> origin/testcommit887
4878 = [up to date] testcommit888 -> origin/testcommit888
4879 = [up to date] testcommit889 -> origin/testcommit889
4880 = [up to date] testcommit89 -> origin/testcommit89
4881 = [up to date] testcommit890 -> origin/testcommit890
4882 = [up to date] testcommit891 -> origin/testcommit891
4883 = [up to date] testcommit892 -> origin/testcommit892
4884 = [up to date] testcommit893 -> origin/testcommit893
4885 = [up to date] testcommit894 -> origin/testcommit894
4886 = [up to date] testcommit895 -> origin/testcommit895
4887 = [up to date] testcommit896 -> origin/testcommit896
4888 = [up to date] testcommit897 -> origin/testcommit897
4889 = [up to date] testcommit898 -> origin/testcommit898
4890 = [up to date] testcommit899 -> origin/testcommit899
4891 = [up to date] testcommit9 -> origin/testcommit9
4892 = [up to date] testcommit90 -> origin/testcommit90
4893 = [up to date] testcommit900 -> origin/testcommit900
4894 = [up to date] testcommit901 -> origin/testcommit901
4895 = [up to date] testcommit902 -> origin/testcommit902
4896 = [up to date] testcommit903 -> origin/testcommit903
4897 = [up to date] testcommit904 -> origin/testcommit904
4898 = [up to date] testcommit905 -> origin/testcommit905
4899 = [up to date] testcommit906 -> origin/testcommit906
4900 = [up to date] testcommit907 -> origin/testcommit907
4901 = [up to date] testcommit908 -> origin/testcommit908
4902 = [up to date] testcommit909 -> origin/testcommit909
4903 = [up to date] testcommit91 -> origin/testcommit91
4904 = [up to date] testcommit910 -> origin/testcommit910
4905 = [up to date] testcommit911 -> origin/testcommit911
4906 = [up to date] testcommit912 -> origin/testcommit912
4907 = [up to date] testcommit913 -> origin/testcommit913
4908 = [up to date] testcommit914 -> origin/testcommit914
4909 = [up to date] testcommit915 -> origin/testcommit915
4910 = [up to date] testcommit916 -> origin/testcommit916
4911 = [up to date] testcommit917 -> origin/testcommit917
4912 = [up to date] testcommit918 -> origin/testcommit918
4913 = [up to date] testcommit919 -> origin/testcommit919
4914 = [up to date] testcommit92 -> origin/testcommit92
4915 = [up to date] testcommit920 -> origin/testcommit920
4916 = [up to date] testcommit921 -> origin/testcommit921
4917 = [up to date] testcommit922 -> origin/testcommit922
4918 = [up to date] testcommit923 -> origin/testcommit923
4919 = [up to date] testcommit924 -> origin/testcommit924
4920 = [up to date] testcommit925 -> origin/testcommit925
4921 = [up to date] testcommit926 -> origin/testcommit926
4922 = [up to date] testcommit927 -> origin/testcommit927
4923 = [up to date] testcommit928 -> origin/testcommit928
4924 = [up to date] testcommit929 -> origin/testcommit929
4925 = [up to date] testcommit93 -> origin/testcommit93
4926 = [up to date] testcommit930 -> origin/testcommit930
4927 = [up to date] testcommit931 -> origin/testcommit931
4928 = [up to date] testcommit932 -> origin/testcommit932
4929 = [up to date] testcommit933 -> origin/testcommit933
4930 = [up to date] testcommit934 -> origin/testcommit934
4931 = [up to date] testcommit935 -> origin/testcommit935
4932 = [up to date] testcommit936 -> origin/testcommit936
4933 = [up to date] testcommit937 -> origin/testcommit937
4934 = [up to date] testcommit938 -> origin/testcommit938
4935 = [up to date] testcommit939 -> origin/testcommit939
4936 = [up to date] testcommit94 -> origin/testcommit94
4937 = [up to date] testcommit940 -> origin/testcommit940
4938 = [up to date] testcommit941 -> origin/testcommit941
4939 = [up to date] testcommit942 -> origin/testcommit942
4940 = [up to date] testcommit943 -> origin/testcommit943
4941 = [up to date] testcommit944 -> origin/testcommit944
4942 = [up to date] testcommit945 -> origin/testcommit945
4943 = [up to date] testcommit946 -> origin/testcommit946
4944 = [up to date] testcommit947 -> origin/testcommit947
4945 = [up to date] testcommit948 -> origin/testcommit948
4946 = [up to date] testcommit949 -> origin/testcommit949
4947 = [up to date] testcommit95 -> origin/testcommit95
4948 = [up to date] testcommit950 -> origin/testcommit950
4949 = [up to date] testcommit951 -> origin/testcommit951
4950 = [up to date] testcommit952 -> origin/testcommit952
4951 = [up to date] testcommit953 -> origin/testcommit953
4952 = [up to date] testcommit954 -> origin/testcommit954
4953 = [up to date] testcommit955 -> origin/testcommit955
4954 = [up to date] testcommit956 -> origin/testcommit956
4955 = [up to date] testcommit957 -> origin/testcommit957
4956 = [up to date] testcommit958 -> origin/testcommit958
4957 = [up to date] testcommit959 -> origin/testcommit959
4958 = [up to date] testcommit96 -> origin/testcommit96
4959 = [up to date] testcommit960 -> origin/testcommit960
4960 = [up to date] testcommit961 -> origin/testcommit961
4961 = [up to date] testcommit962 -> origin/testcommit962
4962 = [up to date] testcommit963 -> origin/testcommit963
4963 = [up to date] testcommit964 -> origin/testcommit964
4964 = [up to date] testcommit965 -> origin/testcommit965
4965 = [up to date] testcommit966 -> origin/testcommit966
4966 = [up to date] testcommit967 -> origin/testcommit967
4967 = [up to date] testcommit968 -> origin/testcommit968
4968 = [up to date] testcommit969 -> origin/testcommit969
4969 = [up to date] testcommit97 -> origin/testcommit97
4970 = [up to date] testcommit970 -> origin/testcommit970
4971 = [up to date] testcommit971 -> origin/testcommit971
4972 = [up to date] testcommit972 -> origin/testcommit972
4973 = [up to date] testcommit973 -> origin/testcommit973
4974 = [up to date] testcommit974 -> origin/testcommit974
4975 = [up to date] testcommit975 -> origin/testcommit975
4976 = [up to date] testcommit976 -> origin/testcommit976
4977 = [up to date] testcommit977 -> origin/testcommit977
4978 = [up to date] testcommit978 -> origin/testcommit978
4979 = [up to date] testcommit979 -> origin/testcommit979
4980 = [up to date] testcommit98 -> origin/testcommit98
4981 = [up to date] testcommit980 -> origin/testcommit980
4982 = [up to date] testcommit981 -> origin/testcommit981
4983 = [up to date] testcommit982 -> origin/testcommit982
4984 = [up to date] testcommit983 -> origin/testcommit983
4985 = [up to date] testcommit984 -> origin/testcommit984
4986 = [up to date] testcommit985 -> origin/testcommit985
4987 = [up to date] testcommit986 -> origin/testcommit986
4988 = [up to date] testcommit987 -> origin/testcommit987
4989 = [up to date] testcommit988 -> origin/testcommit988
4990 = [up to date] testcommit989 -> origin/testcommit989
4991 = [up to date] testcommit99 -> origin/testcommit99
4992 = [up to date] testcommit990 -> origin/testcommit990
4993 = [up to date] testcommit991 -> origin/testcommit991
4994 = [up to date] testcommit992 -> origin/testcommit992
4995 = [up to date] testcommit993 -> origin/testcommit993
4996 = [up to date] testcommit994 -> origin/testcommit994
4997 = [up to date] testcommit995 -> origin/testcommit995
4998 = [up to date] testcommit996 -> origin/testcommit996
4999 = [up to date] testcommit997 -> origin/testcommit997
5000 = [up to date] testcommit998 -> origin/testcommit998
5001 = [up to date] testcommit999 -> origin/testcommit999
+0
-7
git/test/fixtures/ls_tree_a less more
0 100644 blob 81d2c27608b352814cbe979a6acd678d30219678 History.txt
1 100644 blob 641972d82c6d1b51122274ae8f6a0ecdfb56ee22 Manifest.txt
2 100644 blob 8b1e02c0fb554eed2ce2ef737a68bb369d7527df README.txt
3 100644 blob 735d7338b7cb208563aa282f0376c5c4049453a7 Rakefile
4 040000 tree c3d07b0083f01a6e1ac969a0f32b8d06f20c62e5 bin
5 040000 tree aa06ba24b4e3f463b3c4a85469d0fb9e5b421cf8 lib
6 040000 tree 650fa3f0c17f1edb4ae53d8dcca4ac59d86e6c44 test
+0
-2
git/test/fixtures/ls_tree_b less more
0 100644 blob aa94e396335d2957ca92606f909e53e7beaf3fbb grit.rb
1 040000 tree 34868e6e7384cb5ee51c543a8187fdff2675b5a7 grit
+0
-3
git/test/fixtures/ls_tree_commit less more
0 040000 tree 2afb47bcedf21663580d5e6d2f406f08f3f65f19 foo
1 160000 commit d35b34c6e931b9da8f6941007a92c9c9a9b0141a bar
2 040000 tree f623ee576a09ca491c4a27e48c0dfe04be5f4a2e baz
+0
-0
git/test/fixtures/ls_tree_empty less more
(Empty file)
+0
-460
git/test/fixtures/reflog_HEAD less more
0 501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <byronimo@gmail.com> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
1 82b8902e033430000481eb355733cd7065342037 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <byronimo@gmail.com> 1271229940 +0200 commit: conf.py: Adjusted version to match with the actual version
2 69361d96a59381fde0ac34d19df2d4aff05fb9a9 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <byronimo@gmail.com> 1272612605 +0200 checkout: moving from 69361d96a59381fde0ac34d19df2d4aff05fb9a9 to integration
3 69361d96a59381fde0ac34d19df2d4aff05fb9a9 b75c3103a700ac65b6cd18f66e2d0a07cfc09797 Sebastian Thiel <byronimo@gmail.com> 1272612605 +0200 pull git://gitorious.org/git-python/mainline.git refs/merge-requests/14: Merge made by recursive.
4 b75c3103a700ac65b6cd18f66e2d0a07cfc09797 0d6ceabf5b90e7c0690360fc30774d36644f563c Sebastian Thiel <byronimo@gmail.com> 1272614223 +0200 commit: Added additional tz_offset testing in performance test to call it more often.
5 0d6ceabf5b90e7c0690360fc30774d36644f563c 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <byronimo@gmail.com> 1272614242 +0200 checkout: moving from integration to master
6 69361d96a59381fde0ac34d19df2d4aff05fb9a9 0d6ceabf5b90e7c0690360fc30774d36644f563c Sebastian Thiel <byronimo@gmail.com> 1272614247 +0200 merge integration: Fast-forward
7 0d6ceabf5b90e7c0690360fc30774d36644f563c 997b7611dc5ec41d0e3860e237b530f387f3524a Sebastian Thiel <byronimo@gmail.com> 1272874921 +0200 checkout: moving from master to 997b7611dc5ec41d0e3860e237b530f387f3524a
8 997b7611dc5ec41d0e3860e237b530f387f3524a 0d6ceabf5b90e7c0690360fc30774d36644f563c Sebastian Thiel <byronimo@gmail.com> 1272919096 +0200 checkout: moving from 997b7611dc5ec41d0e3860e237b530f387f3524a to master
9 22a0289972b365b7912340501b52ca3dd98be289 143b927307d46ccb8f1cc095739e9625c03c82ff Sebastian Thiel <byronimo@gmail.com> 1272988814 +0200 commit: TODO: Removed all entries but left a mesage about where to find the issuee on lighthouse.
10 143b927307d46ccb8f1cc095739e9625c03c82ff e41c727be8dbf8f663e67624b109d9f8b135a4ab Sebastian Thiel <byronimo@gmail.com> 1273140152 +0200 commit: README: Added mailing list and issue tracker information
11 c083f3d0b853e723d0d4b00ff2f1ec5f65f05cba c083f3d0b853e723d0d4b00ff2f1ec5f65f05cba Sebastian Thiel <byronimo@gmail.com> 1273522280 +0200 checkout: moving from c083f3d0b853e723d0d4b00ff2f1ec5f65f05cba to integration
12 c083f3d0b853e723d0d4b00ff2f1ec5f65f05cba de5bc8f7076c5736ef1efa57345564fbc563bd19 Sebastian Thiel <byronimo@gmail.com> 1273522570 +0200 commit: Handle filenames with embedded spaces when generating diffs
13 de5bc8f7076c5736ef1efa57345564fbc563bd19 8caeec1b15645fa53ec5ddc6e990e7030ffb7c5a Sebastian Thiel <byronimo@gmail.com> 1273529174 +0200 commit: IndexFile.add: Fixed incorrect path handling if path rewriting was desired and absolute paths were given
14 600fcbc1a2d723f8d51e5f5ab6d9e4c389010e1c de5bc8f7076c5736ef1efa57345564fbc563bd19 Sebastian Thiel <byronimo@gmail.com> 1274808939 +0200 checkout: moving from master to master~2
15 de5bc8f7076c5736ef1efa57345564fbc563bd19 600fcbc1a2d723f8d51e5f5ab6d9e4c389010e1c Sebastian Thiel <byronimo@gmail.com> 1274808999 +0200 checkout: moving from de5bc8f7076c5736ef1efa57345564fbc563bd19 to master
16 600fcbc1a2d723f8d51e5f5ab6d9e4c389010e1c c083f3d0b853e723d0d4b00ff2f1ec5f65f05cba Sebastian Thiel <byronimo@gmail.com> 1274809635 +0200 checkout: moving from master to HEAD~3
17 c083f3d0b853e723d0d4b00ff2f1ec5f65f05cba 600fcbc1a2d723f8d51e5f5ab6d9e4c389010e1c Sebastian Thiel <byronimo@gmail.com> 1274809694 +0200 checkout: moving from c083f3d0b853e723d0d4b00ff2f1ec5f65f05cba to master
18 600fcbc1a2d723f8d51e5f5ab6d9e4c389010e1c 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af Sebastian Thiel <byronimo@gmail.com> 1274811103 +0200 commit: diff: by limiting the splitcount to 5, a subtle bug was introduced as the newline at the end of the split line was not split away automatically. Added test for this, and the trivial fix
19 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af 17af1f64d5f1e62d40e11b75b1dd48e843748b49 Sebastian Thiel <byronimo@gmail.com> 1274877948 +0200 commit: BlockingLockFile: added sanity check that raises IOError if the directory containing the lock was removed. This is unlikely to happen in a production envrironment, but may happen during testing, as folders are moved/deleted once the test is complete. Daemons might still be waiting for something, and they should be allowed to terminate instead of waiting for a possibly long time
20 17af1f64d5f1e62d40e11b75b1dd48e843748b49 34ba8ffba0b3b4d21da7bcea594cc3631e422142 Sebastian Thiel <byronimo@gmail.com> 1274906080 +0200 commit: refs: a Reference can now be created by assigning a commit or object (for convenience)
21 34ba8ffba0b3b4d21da7bcea594cc3631e422142 11dc82538cc1ebb537c866c8e76146e384cdfe24 Sebastian Thiel <byronimo@gmail.com> 1274906333 +0200 commit: refs: a Reference can now be created by assigning a commit or object (for convenience)
22 11dc82538cc1ebb537c866c8e76146e384cdfe24 34ba8ffba0b3b4d21da7bcea594cc3631e422142 Sebastian Thiel <byronimo@gmail.com> 1274906338 +0200 HEAD~1: updating HEAD
23 34ba8ffba0b3b4d21da7bcea594cc3631e422142 de84cbdd0f9ef97fcd3477b31b040c57192e28d9 Sebastian Thiel <byronimo@gmail.com> 1274906431 +0200 commit (amend): refs: a Reference can now be created by assigning a commit or object (for convenience)
24 de84cbdd0f9ef97fcd3477b31b040c57192e28d9 ecf37a1b4c2f70f1fc62a6852f40178bf08b9859 Sebastian Thiel <byronimo@gmail.com> 1274910053 +0200 commit: index: index-add fixed to always append a newline after each item. In git has unified its way it reads from stdin, now it wants all items to be terminated by a newline usually. Previously, it could have been that it really didn't want to have a termination character when the last item was written to the file. Bumped the minimum requirements to 1.7.0 to be sure it is working as I think it will.
25 ecf37a1b4c2f70f1fc62a6852f40178bf08b9859 1ee2afb00afaf77c883501eac8cd614c8229a444 Sebastian Thiel <byronimo@gmail.com> 1274914700 +0200 commit: cmd: By default, on linux, the parent file handles will be closed to leave the child less cluttered, and make it easier to debug as it will only have the file descriptors we set. It appears to be more stable regarding the stdin-is-closed-but-child-doesn't-realize-this issue
26 1ee2afb00afaf77c883501eac8cd614c8229a444 bd45e9267ab0d3f37e59ecc8b87d0ad19abad4ad Sebastian Thiel <byronimo@gmail.com> 1275324366 +0200 commit: gitcmd: may now receive extra keyword arguments to be passed directly to the subproces.Popen invocation. It could be used to pass custom environments, without changing the own one
27 bd45e9267ab0d3f37e59ecc8b87d0ad19abad4ad 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e Sebastian Thiel <byronimo@gmail.com> 1275324409 +0200 commit (amend): gitcmd: may now receive extra keyword arguments to be passed directly to the subproces.Popen invocation. It could be used to pass custom environments, without changing the own one (#26)
28 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e Sebastian Thiel <byronimo@gmail.com> 1275417756 +0200 checkout: moving from master to commit
29 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e 14212649c0c48d0a7e5a83430873cae20aad4c83 Sebastian Thiel <byronimo@gmail.com> 1275432496 +0200 commit: commit: initial version of commit_from_tree which could create commit objects if it could serialize itself
30 14212649c0c48d0a7e5a83430873cae20aad4c83 7f6aa55077819e04dace82bc3ffbdea641b3e9ce Sebastian Thiel <byronimo@gmail.com> 1275432507 +0200 commit: commit: initial version of commit_from_tree which could create commit objects if it could serialize itself
31 7f6aa55077819e04dace82bc3ffbdea641b3e9ce 14212649c0c48d0a7e5a83430873cae20aad4c83 Sebastian Thiel <byronimo@gmail.com> 1275432513 +0200 HEAD~1: updating HEAD
32 14212649c0c48d0a7e5a83430873cae20aad4c83 1a0ec7154ea961d68ecfd4dec50f9fc1718686a2 Sebastian Thiel <byronimo@gmail.com> 1275433336 +0200 commit (amend): commit: initial version of commit_from_tree which could create commit objects if it could serialize itself
33 1a0ec7154ea961d68ecfd4dec50f9fc1718686a2 df0892351a394d768489b5647d47b73c24d3ef5f Sebastian Thiel <byronimo@gmail.com> 1275433456 +0200 commit (amend): commit: initial version of commit_from_tree which could create commit objects if it could serialize itself
34 df0892351a394d768489b5647d47b73c24d3ef5f df0892351a394d768489b5647d47b73c24d3ef5f Sebastian Thiel <byronimo@gmail.com> 1275474032 +0200 checkout: moving from commit to odb
35 df0892351a394d768489b5647d47b73c24d3ef5f 0e88ee839eaa5966f0d652372247fd14d80f9bb3 Sebastian Thiel <byronimo@gmail.com> 1275474633 +0200 commit: commit: refactored existing code to decode commits from streams - unfortunately this involves a little bit more python involvement currently, so performance might be slightly worse than before atm
36 0e88ee839eaa5966f0d652372247fd14d80f9bb3 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e Sebastian Thiel <byronimo@gmail.com> 1275474676 +0200 checkout: moving from odb to master
37 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e 0e88ee839eaa5966f0d652372247fd14d80f9bb3 Sebastian Thiel <byronimo@gmail.com> 1275474732 +0200 checkout: moving from master to odb
38 0e88ee839eaa5966f0d652372247fd14d80f9bb3 714e42d6315806dff61d39d8750ef8b250fb8d82 Sebastian Thiel <byronimo@gmail.com> 1275475614 +0200 commit (amend): commit: refactored existing code to decode commits from streams - performance is slightly better
39 714e42d6315806dff61d39d8750ef8b250fb8d82 8c1a87d11df666d308d14e4ae7ee0e9d614296b6 Sebastian Thiel <byronimo@gmail.com> 1275475865 +0200 commit (amend): commit: refactored existing code to decode commits from streams - performance is slightly better
40 8c1a87d11df666d308d14e4ae7ee0e9d614296b6 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e Sebastian Thiel <byronimo@gmail.com> 1275475911 +0200 checkout: moving from odb to master
41 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e 8c1a87d11df666d308d14e4ae7ee0e9d614296b6 Sebastian Thiel <byronimo@gmail.com> 1275475929 +0200 checkout: moving from master to odb
42 8c1a87d11df666d308d14e4ae7ee0e9d614296b6 8c1a87d11df666d308d14e4ae7ee0e9d614296b6 Sebastian Thiel <byronimo@gmail.com> 1275476474 +0200 checkout: moving from odb to perftest
43 8c1a87d11df666d308d14e4ae7ee0e9d614296b6 4a25347d7f4c371345da2348ac6cceec7a143da2 Sebastian Thiel <byronimo@gmail.com> 1275476487 +0200 commit: Added commit-iteration test
44 4a25347d7f4c371345da2348ac6cceec7a143da2 4e1c89ec97ec90037583e85d0e9e71e9c845a19b Sebastian Thiel <byronimo@gmail.com> 1275488012 +0200 commit: Added performance testing foundation library, reworked existing performance tests to work on larger repositories
45 4e1c89ec97ec90037583e85d0e9e71e9c845a19b ae5a69f67822d81bbbd8f4af93be68703e730b37 Sebastian Thiel <byronimo@gmail.com> 1275489688 +0200 commit: commit: redesigned revlist and commit parsing, commits are always retrieved from their object information directly. This is faster, and resolves issues with the rev-list format and empty commit messages
46 ae5a69f67822d81bbbd8f4af93be68703e730b37 02004a7ea4d26dc45f194d3a34780a50634ef497 Sebastian Thiel <byronimo@gmail.com> 1275493157 +0200 commit: git.cmd: added test for stream section constraint used in git command, found bug of course which just didn't kick in yet
47 02004a7ea4d26dc45f194d3a34780a50634ef497 ae5a69f67822d81bbbd8f4af93be68703e730b37 Sebastian Thiel <byronimo@gmail.com> 1275493169 +0200 HEAD~1: updating HEAD
48 ae5a69f67822d81bbbd8f4af93be68703e730b37 538820055ce1bf9dd07ecda48210832f96194504 Sebastian Thiel <byronimo@gmail.com> 1275493189 +0200 commit: git.cmd: added test for stream section constraint used in git command, found bug of course which just didn't kick in yet
49 538820055ce1bf9dd07ecda48210832f96194504 282018b79cc8df078381097cb3aeb29ff56e83c6 Sebastian Thiel <byronimo@gmail.com> 1275502260 +0200 commit: Added first design and frame for object database. In a first step, loose objects will be written using our utilities, and certain object retrieval functionality moves into the GitObjectDatabase which is used by the repo instance
50 282018b79cc8df078381097cb3aeb29ff56e83c6 8c1a87d11df666d308d14e4ae7ee0e9d614296b6 Sebastian Thiel <byronimo@gmail.com> 1275502285 +0200 checkout: moving from perftest to odb
51 8c1a87d11df666d308d14e4ae7ee0e9d614296b6 282018b79cc8df078381097cb3aeb29ff56e83c6 Sebastian Thiel <byronimo@gmail.com> 1275502288 +0200 merge perftest: Fast-forward
52 282018b79cc8df078381097cb3aeb29ff56e83c6 8b86f9b399a8f5af792a04025fdeefc02883f3e5 Sebastian Thiel <byronimo@gmail.com> 1275511252 +0200 commit: initial version of loose object writing and simple cached object lookup appears to be working
53 8b86f9b399a8f5af792a04025fdeefc02883f3e5 6f8ce8901e21587cd2320562df412e05b5ab1731 Sebastian Thiel <byronimo@gmail.com> 1275515609 +0200 commit: added frame for object reading, including simple test
54 6f8ce8901e21587cd2320562df412e05b5ab1731 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e Sebastian Thiel <byronimo@gmail.com> 1275549198 +0200 checkout: moving from odb to master
55 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e e79999c956e2260c37449139080d351db4aa3627 Sebastian Thiel <byronimo@gmail.com> 1275549608 +0200 commit: git.cmd: moved hardcoded chunksize when duplicating stream data into easy-to-change class member variable
56 e79999c956e2260c37449139080d351db4aa3627 6f8ce8901e21587cd2320562df412e05b5ab1731 Sebastian Thiel <byronimo@gmail.com> 1275549707 +0200 checkout: moving from master to odb
57 6f8ce8901e21587cd2320562df412e05b5ab1731 e79999c956e2260c37449139080d351db4aa3627 Sebastian Thiel <byronimo@gmail.com> 1275550120 +0200 checkout: moving from odb to master
58 e79999c956e2260c37449139080d351db4aa3627 412632599479a8e5991a07ecb67bc52b85c60755 Sebastian Thiel <byronimo@gmail.com> 1275550524 +0200 commit: git.cmd: using communicate in the main branch of execution, which might not make a big difference, but perhaps its smarter about broken pipes.
59 412632599479a8e5991a07ecb67bc52b85c60755 25dca42bac17d511b7e2ebdd9d1d679e7626db5f Sebastian Thiel <byronimo@gmail.com> 1275550670 +0200 commit (amend): git.cmd: using communicate in the main branch of execution, which might not make a big difference, but perhaps its smarter about broken pipes.
60 25dca42bac17d511b7e2ebdd9d1d679e7626db5f 6f8ce8901e21587cd2320562df412e05b5ab1731 Sebastian Thiel <byronimo@gmail.com> 1275551315 +0200 checkout: moving from master to odb
61 6f8ce8901e21587cd2320562df412e05b5ab1731 38d59fc8ccccae8882fa48671377bf40a27915a7 Sebastian Thiel <byronimo@gmail.com> 1275575735 +0200 commit: odb: implemented loose object streaming, which is impossible to do efficiently considering that it copies string buffers all the time
62 38d59fc8ccccae8882fa48671377bf40a27915a7 26e138cb47dccc859ff219f108ce9b7d96cbcbcd Sebastian Thiel <byronimo@gmail.com> 1275582065 +0200 commit: odb: fixed streamed decompression reader ( specific tests would still be missing ) and added performance tests which are extremely promising
63 26e138cb47dccc859ff219f108ce9b7d96cbcbcd 4295787b65d4a85ac1e0e20741aa59ec19a97353 Sebastian Thiel <byronimo@gmail.com> 1275584658 +0200 commit: Added performance comparison to cgit ... and yes, git-python is faster :)
64 4295787b65d4a85ac1e0e20741aa59ec19a97353 4b4a514e51fbc7dc6ddcb27c188159d57b5d1fa9 Sebastian Thiel <byronimo@gmail.com> 1275590443 +0200 commit (amend): Added performance comparison to cgit ... and yes, git-python is faster :)
65 4b4a514e51fbc7dc6ddcb27c188159d57b5d1fa9 1e2b46138ba58033738a24dadccc265748fce2ca Sebastian Thiel <byronimo@gmail.com> 1275600034 +0200 commit: commit.create_from_tree now uses pure python implementation, fixed message parsing which truncated newlines although it was ilegitimate. Its up to the reader to truncate therse, nowhere in the git code I could find anyone adding newlines to commits where it is written
66 1e2b46138ba58033738a24dadccc265748fce2ca 1906ee4df9ae4e734288c5203cf79894dff76cab Sebastian Thiel <byronimo@gmail.com> 1275600429 +0200 commit: Fixed compatability issues with python 2.5, made sure all tests run
67 1906ee4df9ae4e734288c5203cf79894dff76cab b01ca6a3e4ae9d944d799743c8ff774e2a7a82b6 Sebastian Thiel <byronimo@gmail.com> 1275602940 +0200 commit: db: implemented GitObjectDB using the git command to make sure we can lookup everything. Next is to implement pack-file reading, then alternates which should allow to resolve everything
68 b01ca6a3e4ae9d944d799743c8ff774e2a7a82b6 b01ca6a3e4ae9d944d799743c8ff774e2a7a82b6 Sebastian Thiel <byronimo@gmail.com> 1275643039 +0200 checkout: moving from odb to asyncredesign
69 b01ca6a3e4ae9d944d799743c8ff774e2a7a82b6 a1e80445ad5cb6da4c0070d7cb8af89da3b0803b Sebastian Thiel <byronimo@gmail.com> 1275655275 +0200 commit: initial version of new odb design to facilitate a channel based multi-threading implementation of all odb functions
70 a1e80445ad5cb6da4c0070d7cb8af89da3b0803b e746f96bcc29238b79118123028ca170adc4ff0f Sebastian Thiel <byronimo@gmail.com> 1275664928 +0200 commit: Fixed implementation after design change to deal with it - all tests run, but next there will have to be more through testing
71 e746f96bcc29238b79118123028ca170adc4ff0f b01ca6a3e4ae9d944d799743c8ff774e2a7a82b6 Sebastian Thiel <byronimo@gmail.com> 1275664939 +0200 checkout: moving from asyncredesign to odb
72 b01ca6a3e4ae9d944d799743c8ff774e2a7a82b6 e746f96bcc29238b79118123028ca170adc4ff0f Sebastian Thiel <byronimo@gmail.com> 1275664943 +0200 merge asyncredesign: Fast-forward
73 e746f96bcc29238b79118123028ca170adc4ff0f 25dca42bac17d511b7e2ebdd9d1d679e7626db5f Sebastian Thiel <byronimo@gmail.com> 1275664990 +0200 checkout: moving from odb to master
74 25dca42bac17d511b7e2ebdd9d1d679e7626db5f 6fbb69306c0e14bacb8dcb92a89af27d3d5d631f Sebastian Thiel <byronimo@gmail.com> 1275665431 +0200 commit (merge): Merge branch 'odb'
75 6fbb69306c0e14bacb8dcb92a89af27d3d5d631f a243827ab3346e188e99db2f9fc1f916941c9b1a Sebastian Thiel <byronimo@gmail.com> 1275685591 +0200 commit: Implemented stream tests, found a bug on the way, slowly a test-framework for streams starts to show up, but its not yet there
76 a243827ab3346e188e99db2f9fc1f916941c9b1a 7c1169f6ea406fec1e26e99821e18e66437e65eb Sebastian Thiel <byronimo@gmail.com> 1275690001 +0200 commit: Removed compression flag from IStream and OStream types, as a valid object will always be compressed if generated by the system ( even future memory db's will compress it )
77 7c1169f6ea406fec1e26e99821e18e66437e65eb c69b6b979e3d6bd01ec40e75b92b21f7a391f0ca Sebastian Thiel <byronimo@gmail.com> 1275746174 +0200 commit: Added basic channel implementation including test
78 c69b6b979e3d6bd01ec40e75b92b21f7a391f0ca c69b6b979e3d6bd01ec40e75b92b21f7a391f0ca Sebastian Thiel <byronimo@gmail.com> 1275746191 +0200 checkout: moving from master to async
79 c69b6b979e3d6bd01ec40e75b92b21f7a391f0ca c69b6b979e3d6bd01ec40e75b92b21f7a391f0ca Sebastian Thiel <byronimo@gmail.com> 1275746194 +0200 checkout: moving from async to master
80 c69b6b979e3d6bd01ec40e75b92b21f7a391f0ca 7c1169f6ea406fec1e26e99821e18e66437e65eb Sebastian Thiel <byronimo@gmail.com> 1275746196 +0200 HEAD~1: updating HEAD
81 7c1169f6ea406fec1e26e99821e18e66437e65eb c69b6b979e3d6bd01ec40e75b92b21f7a391f0ca Sebastian Thiel <byronimo@gmail.com> 1275746213 +0200 checkout: moving from master to async
82 c69b6b979e3d6bd01ec40e75b92b21f7a391f0ca 65c9fe0baa579173afa5a2d463ac198d06ef4993 Sebastian Thiel <byronimo@gmail.com> 1275746839 +0200 commit: A code donation: Donating a worker thread implementation inclduding tests to Git-Python. I have the feeling it can do much good here :)
83 65c9fe0baa579173afa5a2d463ac198d06ef4993 50e469109eed3a752d9a1b0297f16466ad92f8d2 Sebastian Thiel <byronimo@gmail.com> 1275755186 +0200 commit: Initial pool design added, allowing for lazy channel based evaluation of inter-dependent tasks
84 50e469109eed3a752d9a1b0297f16466ad92f8d2 61138f2ece0cb864b933698174315c34a78835d1 Sebastian Thiel <byronimo@gmail.com> 1275760757 +0200 commit: Moved multiprocessing modules into own package, as they in fact have nothing to do with the object db. If that really works the way I want, it will become an own project, called async
85 61138f2ece0cb864b933698174315c34a78835d1 ab59f78341f1dd188aaf4c30526f6295c63438b1 Sebastian Thiel <byronimo@gmail.com> 1275760989 +0200 commit: Renamed mp to async, as this is a much better name for what is actually going on. The default implementation uses threads, which ends up being nothing more than async, as they are all locked down by internal and the global interpreter lock
86 ab59f78341f1dd188aaf4c30526f6295c63438b1 b72e2704022d889f116e49abf3e1e5d3e3192d3b Sebastian Thiel <byronimo@gmail.com> 1275778812 +0200 commit: Improved pool design and started rough implementation, top down to learn while going. Tests will be written soon for verification, its still quite theoretical
87 b72e2704022d889f116e49abf3e1e5d3e3192d3b ec28ad575ce1d7bb6a616ffc404f32bbb1af67b2 Sebastian Thiel <byronimo@gmail.com> 1275821305 +0200 commit: thread: adjusted worker thread not to provide an output queue anymore - this is handled by the task system
88 ec28ad575ce1d7bb6a616ffc404f32bbb1af67b2 b3cde0ee162b8f0cb67da981311c8f9c16050a62 Sebastian Thiel <byronimo@gmail.com> 1275840801 +0200 commit: First step of testing the pool - tasks have been separated into a new module including own tests, their design improved to prepare them for some specifics that would be needed for multiprocessing support
89 b3cde0ee162b8f0cb67da981311c8f9c16050a62 8d74950510bbd74aa06afe4ec4c19e4739462d6a Sebastian Thiel <byronimo@gmail.com> 1275851713 +0200 commit: Plenty of fixes in the chunking routine, made possible by a serialized chunking test. Next up, actual async processing
90 8d74950510bbd74aa06afe4ec4c19e4739462d6a 1b27292936c81637f6b9a7141dafaad1126f268e Sebastian Thiel <byronimo@gmail.com> 1275852711 +0200 commit (amend): Plenty of fixes in the chunking routine, made possible by a serialized chunking test. Next up, actual async processing
91 1b27292936c81637f6b9a7141dafaad1126f268e 867129e2950458ab75523b920a5e227e3efa8bbc Sebastian Thiel <byronimo@gmail.com> 1275858486 +0200 commit: channel.read: enhanced to be sure we don't run into non-atomicity issues related to our channel closed flag, which is the only way not to block forever on read(0) channels which were closed by a thread 'in the meanwhile'
92 867129e2950458ab75523b920a5e227e3efa8bbc 6335fe0abcedc99145dd1400509b7540568ac2cc Sebastian Thiel <byronimo@gmail.com> 1275860480 +0200 commit: pool: First version which works as expected in async mode. The task model is very simple still, but its getting there
93 6335fe0abcedc99145dd1400509b7540568ac2cc 320c5329995cc8d364a88ba83103e1db584410ce Sebastian Thiel <byronimo@gmail.com> 1275860784 +0200 commit (amend): pool: First version which works as expected in async mode. The task model is very simple still, but its getting there
94 320c5329995cc8d364a88ba83103e1db584410ce d759d0b97aaf5fd60a1df0ea0f60e67863a6c3d7 Sebastian Thiel <byronimo@gmail.com> 1275861899 +0200 commit (amend): pool: First version which works as expected in async mode. The task model is very simple still, but its getting there
95 d759d0b97aaf5fd60a1df0ea0f60e67863a6c3d7 6a252661c3bf4202a4d571f9c41d2afa48d9d75f Sebastian Thiel <byronimo@gmail.com> 1275861909 +0200 commit (amend): pool: First version which works as expected in async mode. Its just using a single task for now, but next up are dependent tasks
96 6a252661c3bf4202a4d571f9c41d2afa48d9d75f a8a448b7864e21db46184eab0f0a21d7725d074f Sebastian Thiel <byronimo@gmail.com> 1275899902 +0200 commit: pool.consumed_tasks: is now a queue to be thread safe, in preparation for multiple connected pools
97 a8a448b7864e21db46184eab0f0a21d7725d074f 856af48fbffaf1b935d513429afeb319e4795d2d Sebastian Thiel <byronimo@gmail.com> 1275905456 +0200 commit: changed scheduling and chunksize calculation in respect to the task.min_count. Previously, it would possibly not produce enough items in case T1 wants to produce less items than t2 needs ... in fact, it would work even then, committing this anyway
98 856af48fbffaf1b935d513429afeb319e4795d2d 619662a9138fd78df02c52cae6dc89db1d70a0e5 Sebastian Thiel <byronimo@gmail.com> 1275905984 +0200 commit (amend): changed scheduling and chunksize calculation in respect to the task.min_count, to fix theoretical option for a deadlock in serial mode, and unnecessary blocking in async mode
99 619662a9138fd78df02c52cae6dc89db1d70a0e5 8c3c271b0d6b5f56b86e3f177caf3e916b509b52 Sebastian Thiel <byronimo@gmail.com> 1275908735 +0200 commit: Added task order cache, and a lock to prevent us walking the graph while changing tasks
100 8c3c271b0d6b5f56b86e3f177caf3e916b509b52 edd9e23c766cfd51b3a6f6eee5aac0b791ef2fd0 Sebastian Thiel <byronimo@gmail.com> 1275923808 +0200 commit: added high-speed locking facilities, allowing our Queue to be faster, at least in tests, and with multiple threads. There is still an sync bug in regard to closed channels to be fixed, as the Task.set_done handling is incorrecft
101 edd9e23c766cfd51b3a6f6eee5aac0b791ef2fd0 583cd8807259a69fc01874b798f657c1f9ab7828 Sebastian Thiel <byronimo@gmail.com> 1275930764 +0200 commit: Moved pool utilities into util module, fixed critical issue that caused havok - lets call this a safe-state
102 583cd8807259a69fc01874b798f657c1f9ab7828 654e54d200135e665e07e9f0097d913a77f169da Sebastian Thiel <byronimo@gmail.com> 1275933662 +0200 commit: task: Fixed incorrect handling of channel closure. Performance is alright for up to 2 threads, but 4 are killing the queue
103 654e54d200135e665e07e9f0097d913a77f169da be06e87433685b5ea9cfcc131ab89c56cf8292f2 Sebastian Thiel <byronimo@gmail.com> 1275940847 +0200 commit: improved testing to test the actual async handling of the pool. there are still inconsistencies that need to be fixed, but it already improved, especially the 4-thread performance which now is as fast as the dual-threaded performance
104 be06e87433685b5ea9cfcc131ab89c56cf8292f2 be06e87433685b5ea9cfcc131ab89c56cf8292f2 Sebastian Thiel <byronimo@gmail.com> 1275945495 +0200 checkout: moving from async to stasks
105 be06e87433685b5ea9cfcc131ab89c56cf8292f2 223701e19722afb0f57fc0de6e366ade542efdc0 Sebastian Thiel <byronimo@gmail.com> 1275945637 +0200 commit: introduced a new counter keeping track of the scheduled tasks - this prevent unnecessary tasks to be scheduled as we keep track of how many items will be produced for the task at hand. This introduces additional locking, but performns well in multithreaded mode. Performance of the master queue is still a huge issue, its currently the limiting factor, as bypassing the master queue in serial moode gives 15x performance, wich is what I would need
106 223701e19722afb0f57fc0de6e366ade542efdc0 def0f73989047c4ddf9b11da05ad2c9c8e387331 Sebastian Thiel <byronimo@gmail.com> 1275946081 +0200 commit (amend): introduced a new counter keeping track of the scheduled tasks - this prevent unnecessary tasks to be scheduled as we keep track of how many items will be produced for the task at hand. This introduces additional locking, but performns well in multithreaded mode. Performance of the master queue is still a huge issue, its currently the limiting factor, as bypassing the master queue in serial moode gives 15x performance, wich is what I would need
107 def0f73989047c4ddf9b11da05ad2c9c8e387331 be06e87433685b5ea9cfcc131ab89c56cf8292f2 Sebastian Thiel <byronimo@gmail.com> 1275946086 +0200 checkout: moving from stasks to async
108 be06e87433685b5ea9cfcc131ab89c56cf8292f2 be06e87433685b5ea9cfcc131ab89c56cf8292f2 Sebastian Thiel <byronimo@gmail.com> 1275946311 +0200 checkout: moving from async to brute
109 be06e87433685b5ea9cfcc131ab89c56cf8292f2 293fa4de92c789d67de6a663d7b14a6897b14181 Sebastian Thiel <byronimo@gmail.com> 1275946483 +0200 commit: Removed qsize dependency when reading , now it puts onto the queue everytime someone reads. This does not appear very stable for now as one can, for some reason, deplete the channel, which can only happen if its closed before all tasks finish, which should already be fixed
110 293fa4de92c789d67de6a663d7b14a6897b14181 def0f73989047c4ddf9b11da05ad2c9c8e387331 Sebastian Thiel <byronimo@gmail.com> 1275946494 +0200 checkout: moving from brute to stasks
111 def0f73989047c4ddf9b11da05ad2c9c8e387331 e825f8b69760e269218b1bf1991018baf3c16b04 Sebastian Thiel <byronimo@gmail.com> 1275946688 +0200 commit: Channel now uses the AsyncQueue, boosting performance by factor 4, its a start
112 e825f8b69760e269218b1bf1991018baf3c16b04 898d47d1711accdfded8ee470520fdb96fb12d46 Sebastian Thiel <byronimo@gmail.com> 1275947226 +0200 commit: Task scheduled items lock now uses a dummy lock in serial mode, improving its performance considerably.
113 898d47d1711accdfded8ee470520fdb96fb12d46 be06e87433685b5ea9cfcc131ab89c56cf8292f2 Sebastian Thiel <byronimo@gmail.com> 1275947355 +0200 checkout: moving from stasks to async
114 be06e87433685b5ea9cfcc131ab89c56cf8292f2 3e2ba9c2028f21d11988558f3557905d21e93808 Sebastian Thiel <byronimo@gmail.com> 1275947360 +0200 merge stasks: Merge made by recursive.
115 3e2ba9c2028f21d11988558f3557905d21e93808 7c1169f6ea406fec1e26e99821e18e66437e65eb Sebastian Thiel <byronimo@gmail.com> 1275948503 +0200 checkout: moving from async to master
116 7c1169f6ea406fec1e26e99821e18e66437e65eb 3e2ba9c2028f21d11988558f3557905d21e93808 Sebastian Thiel <byronimo@gmail.com> 1275948509 +0200 checkout: moving from master to async
117 3e2ba9c2028f21d11988558f3557905d21e93808 3e2ba9c2028f21d11988558f3557905d21e93808 Sebastian Thiel <byronimo@gmail.com> 1275948864 +0200 checkout: moving from async to queue
118 3e2ba9c2028f21d11988558f3557905d21e93808 5d996892ac76199886ba3e2754ff9c9fac2456d6 Sebastian Thiel <byronimo@gmail.com> 1275949953 +0200 commit: test implementation of async-queue with everything stripped from it that didn't seem necessary - its a failure, something is wrong - performance not much better than the original one, its depending on the condition performance actually, which I don't get faster
119 5d996892ac76199886ba3e2754ff9c9fac2456d6 3e2ba9c2028f21d11988558f3557905d21e93808 Sebastian Thiel <byronimo@gmail.com> 1275949960 +0200 checkout: moving from queue to async
120 3e2ba9c2028f21d11988558f3557905d21e93808 5d996892ac76199886ba3e2754ff9c9fac2456d6 Sebastian Thiel <byronimo@gmail.com> 1275979377 +0200 checkout: moving from async to queue
121 5d996892ac76199886ba3e2754ff9c9fac2456d6 3e2ba9c2028f21d11988558f3557905d21e93808 Sebastian Thiel <byronimo@gmail.com> 1275979426 +0200 checkout: moving from queue to async
122 3e2ba9c2028f21d11988558f3557905d21e93808 5d996892ac76199886ba3e2754ff9c9fac2456d6 Sebastian Thiel <byronimo@gmail.com> 1275979446 +0200 checkout: moving from async to queue
123 5d996892ac76199886ba3e2754ff9c9fac2456d6 f32ef32960ae8aa8a20c00cd3f7e78b441ee664b Sebastian Thiel <byronimo@gmail.com> 1275986714 +0200 commit: both versions of the async queue still have trouble in certain situations, at least with my totally overwritten version of the condition - the previous one was somewhat more stable it seems
124 f32ef32960ae8aa8a20c00cd3f7e78b441ee664b 09c3f39ceb545e1198ad7a3f470d4ec896ce1add Sebastian Thiel <byronimo@gmail.com> 1275986721 +0200 commit (amend): both versions of the async queue still have trouble in certain situations, at least with my totally overwritten version of the condition - the previous one was somewhat more stable it seems. Nonetheless, this is the fastest version so far
125 09c3f39ceb545e1198ad7a3f470d4ec896ce1add 3776f7a766851058f6435b9f606b16766425d7ca Sebastian Thiel <byronimo@gmail.com> 1275996284 +0200 commit: The new channeldesign actually works, but it also shows that its located at the wrong spot. The channel is nothing more than an adapter allowing to read multiple items from a thread-safe queue, the queue itself though must be 'closable' for writing, or needs something like a writable flag.
126 3776f7a766851058f6435b9f606b16766425d7ca 53152a824f5186452504f0b68306d10ebebee416 Sebastian Thiel <byronimo@gmail.com> 1275999838 +0200 commit: queue: adjusted queue to be closable ( without own testing yet, except for the pool which runs it ) - its not yet stable, but should be solvable.
127 53152a824f5186452504f0b68306d10ebebee416 619c11787742ce00a0ee8f841cec075897873c79 Sebastian Thiel <byronimo@gmail.com> 1276008468 +0200 commit: Its getting better already - intermediate commit before further chaning the task class
128 619c11787742ce00a0ee8f841cec075897873c79 13dd59ba5b3228820841682b59bad6c22476ff66 Sebastian Thiel <byronimo@gmail.com> 1276010743 +0200 commit: task: now deletes itself once its done - for the test this doesn't change a thing as the task deletes itself too late - its time for a paradigm change, the task should be deleted with its RPoolChannel or explicitly by the user. The test needs to adapt, and shouldn't assume anything unless the RPoolChannel is gone
129 13dd59ba5b3228820841682b59bad6c22476ff66 e5c0002d069382db1768349bf0c5ff40aafbf140 Sebastian Thiel <byronimo@gmail.com> 1276014012 +0200 commit: Revised task deletion works well, adjusted test to be creating new tasks all the time instead of reusing its own one, it was somewhat hard to manage its state over time and could cause bugs. It works okay, but it occasionally hangs, it appears to be an empty queue, have to gradually put certain things back in, although in the current mode of operation, it should never have empty queues from the pool to the user
130 e5c0002d069382db1768349bf0c5ff40aafbf140 772b95631916223e472989b43f3a31f61e237f31 Sebastian Thiel <byronimo@gmail.com> 1276017933 +0200 commit: workerthread: adjusted to use a blocking queue, it will receive termination events only with its queue, with boosts performance into brigt green levels
131 772b95631916223e472989b43f3a31f61e237f31 3e2ba9c2028f21d11988558f3557905d21e93808 Sebastian Thiel <byronimo@gmail.com> 1276017957 +0200 checkout: moving from queue to async
132 3e2ba9c2028f21d11988558f3557905d21e93808 f78d4a28f307a9d7943a06be9f919304c25ac2d9 Sebastian Thiel <byronimo@gmail.com> 1276017963 +0200 merge queue: Merge made by recursive.
133 f78d4a28f307a9d7943a06be9f919304c25ac2d9 15941ca090a2c3c987324fc911bbc6f89e941c47 Sebastian Thiel <byronimo@gmail.com> 1276072452 +0200 commit: queue: fixed critical bug in the notify method, as it was not at all thread-safe, causing locks to be released multiple times. Now it runs very fast, and very stable apparently.
134 15941ca090a2c3c987324fc911bbc6f89e941c47 f2c8d26d3b25b864ad48e6de018757266b59f708 Sebastian Thiel <byronimo@gmail.com> 1276075717 +0200 commit: thread: fixed initialization problem if an empty iterable was handed in
135 f2c8d26d3b25b864ad48e6de018757266b59f708 2054561da184955c4be4a92f0b4fa5c5c1c01350 Sebastian Thiel <byronimo@gmail.com> 1276075884 +0200 commit: HSCondition: using a deck to store waiters, for further speedup
136 2054561da184955c4be4a92f0b4fa5c5c1c01350 1090701721888474d34f8a4af28ee1bb1c3fdaaa Sebastian Thiel <byronimo@gmail.com> 1276076141 +0200 commit: HSCondition: now deriving from deque, as the AsyncQeue does, to elimitate one more level of indirection. Clearly this not good from a design standpoint, as a Condition is no Deque, but it helps speeding things up which is what this is about. Could make it a hidden class to indicate how 'special' it is
137 1090701721888474d34f8a4af28ee1bb1c3fdaaa a988e6985849e4f6a561b4a5468d525c25ce74fe Sebastian Thiel <byronimo@gmail.com> 1276076725 +0200 commit: HSCondition: now gets a lock even in the single-notify case, as it was required due to the non-atomiciy of the invovled operation. Removed one level of indirection for the lock, by refraining from calling my own 'wrapper' methods, which brought it back to the performance it had before the locking was introduced for the n==1 case
138 a988e6985849e4f6a561b4a5468d525c25ce74fe 4e6bece08aea01859a232e99a1e1ad8cc1eb7d36 Sebastian Thiel <byronimo@gmail.com> 1276084911 +0200 commit: HSCondition: Fixed terrible bug which it inherited from its default python Condition implementation, related to the notify method not being treadsafe. Although I was aware of it, I missed the first check which tests for the size - the result could be incorrect if the whole method wasn't locked.
139 4e6bece08aea01859a232e99a1e1ad8cc1eb7d36 ffb5b95cb2cec5c5a79234dfc47c3fcf1f724101 Sebastian Thiel <byronimo@gmail.com> 1276087661 +0200 commit: Channel: Read method revised - now it really really doesn't block anymore, and it runs faster as well, about 2/3 of the performance we have when being in serial mode
140 ffb5b95cb2cec5c5a79234dfc47c3fcf1f724101 0974f8737a3c56a7c076f9d0b757c6cb106324fb Sebastian Thiel <byronimo@gmail.com> 1276087839 +0200 commit (amend): Channel: Read method revised - now it really really doesn't block anymore, and it runs faster as well, about 2/3 of the performance we have when being in serial mode
141 0974f8737a3c56a7c076f9d0b757c6cb106324fb 57a4e09294230a36cc874a6272c71757c48139f2 Sebastian Thiel <byronimo@gmail.com> 1276090187 +0200 commit: Channel: removed pseudoconstructor, which clearly improves the design and makes it easier to constomize
142 57a4e09294230a36cc874a6272c71757c48139f2 07996a1a1e53ffdd2680d4bfbc2f4059687859a5 Sebastian Thiel <byronimo@gmail.com> 1276090851 +0200 commit: task: removed scheduled task support, which at some point was introduced to improve performance, but which now hinders performance, besides being unnecessary ;)
143 07996a1a1e53ffdd2680d4bfbc2f4059687859a5 ea81f14dafbfb24d70373c74b5f8dabf3f2225d9 Sebastian Thiel <byronimo@gmail.com> 1276094301 +0200 commit: Channel: Callbacks reviewed - they are now part of Subclasses of the default channel implementation, one of which is used as base by the Pool Read channel, releasing it of the duty to call these itself. The write channel with callback subclass allows the transformation of the item to be written
144 ea81f14dafbfb24d70373c74b5f8dabf3f2225d9 365fb14ced88a5571d3287ff1698582ceacd80d6 Sebastian Thiel <byronimo@gmail.com> 1276095557 +0200 commit: task: redesigned write channel access to allow the task creator to set own write channels, possibly some with callbacks installed etc.. Pool.add_task will respect the users choice now, but provide defaults which are optimized for performance
145 365fb14ced88a5571d3287ff1698582ceacd80d6 257a8a9441fca9a9bc384f673ba86ef5c3f1715d Sebastian Thiel <byronimo@gmail.com> 1276111194 +0200 commit: test: prepared task dependency test, which already helped to find bug in the reference counting mechanism, causing references to the pool to be kepts via cycles
146 257a8a9441fca9a9bc384f673ba86ef5c3f1715d 3323464f85b986cba23176271da92a478b33ab9c Sebastian Thiel <byronimo@gmail.com> 1276122289 +0200 commit: messy first version of a properly working depth-first graph method, which allows the pool to work as expected. Many more tests need to be added, and there still is a problem with shutdown as sometimes it won't kill all threads, mainly because the process came up with worker threads started, which cannot be
147 3323464f85b986cba23176271da92a478b33ab9c 3323464f85b986cba23176271da92a478b33ab9c Sebastian Thiel <byronimo@gmail.com> 1276122375 +0200 checkout: moving from async to async
148 3323464f85b986cba23176271da92a478b33ab9c 257a8a9441fca9a9bc384f673ba86ef5c3f1715d Sebastian Thiel <byronimo@gmail.com> 1276122387 +0200 HEAD~1: updating HEAD
149 257a8a9441fca9a9bc384f673ba86ef5c3f1715d 3323464f85b986cba23176271da92a478b33ab9c Sebastian Thiel <byronimo@gmail.com> 1276122419 +0200 checkout: moving from async to taskdep
150 3323464f85b986cba23176271da92a478b33ab9c cfb278d74ad01f3f1edf5e0ad113974a9555038d Sebastian Thiel <byronimo@gmail.com> 1276157672 +0200 commit: InputChannelTask now has interface for properly handling the reading from the same and different pools
151 cfb278d74ad01f3f1edf5e0ad113974a9555038d 01eac1a959c1fa5894a86bf11e6b92f96762bdd8 Sebastian Thiel <byronimo@gmail.com> 1276164376 +0200 commit: Added more dependency task tests, especially the single-reads are not yet fully deterministic as tasks still run into the problem that they try to write into a closed channel, it was closed by one of their task-mates who didn't know someone else was still computing
152 01eac1a959c1fa5894a86bf11e6b92f96762bdd8 01eac1a959c1fa5894a86bf11e6b92f96762bdd8 Sebastian Thiel <byronimo@gmail.com> 1276166920 +0200 checkout: moving from taskdep to channel
153 01eac1a959c1fa5894a86bf11e6b92f96762bdd8 01eac1a959c1fa5894a86bf11e6b92f96762bdd8 Sebastian Thiel <byronimo@gmail.com> 1276167802 +0200 checkout: moving from channel to taskdep
154 01eac1a959c1fa5894a86bf11e6b92f96762bdd8 01eac1a959c1fa5894a86bf11e6b92f96762bdd8 Sebastian Thiel <byronimo@gmail.com> 1276169390 +0200 checkout: moving from taskdep to channel
155 01eac1a959c1fa5894a86bf11e6b92f96762bdd8 55e757928e493ce93056822d510482e4ffcaac2d Sebastian Thiel <byronimo@gmail.com> 1276173597 +0200 commit: channel: Changed design to be more logical - a channel now has any amount of readers and writers, a ready is not connected to its writer anymore. This changes the refcounting of course, which is why the auto-cleanup for the pool is currently broken.
156 55e757928e493ce93056822d510482e4ffcaac2d 7c36f3648e39ace752c67c71867693ce1eee52a3 Sebastian Thiel <byronimo@gmail.com> 1276177120 +0200 commit: Now tracking the amount of concurrent writers to assure the channel is closed only when there is no one else writing to it. This assures that all tasks can continue working, and put their results accordingly. Shutdown is still not working correctly, but that should be solvable as well. Its still not perfect though ...
157 7c36f3648e39ace752c67c71867693ce1eee52a3 c34343d0b714d2c4657972020afea034a167a682 Sebastian Thiel <byronimo@gmail.com> 1276177952 +0200 commit: tasks can now terminate faster when no items were read, without neglecting their duty to close the channel if required. Code is a little less maintainable now, but faster, it appears
158 c34343d0b714d2c4657972020afea034a167a682 4c2fa54d8122e9e5bc20a938ff8ccc5caf96dafe Sebastian Thiel <byronimo@gmail.com> 1276206673 +0200 commit: tasks can now terminate faster when no items were read, without neglecting their duty to close the channel if required. Code is a little less maintainable now, but faster, it appearsgst
159 4c2fa54d8122e9e5bc20a938ff8ccc5caf96dafe c34343d0b714d2c4657972020afea034a167a682 Sebastian Thiel <byronimo@gmail.com> 1276206682 +0200 HEAD~1: updating HEAD
160 c34343d0b714d2c4657972020afea034a167a682 fbe062bf6dacd3ad63dd827d898337fa542931ac Sebastian Thiel <byronimo@gmail.com> 1276206950 +0200 commit: Added dependency-task tests, and fixed plenty of ref-count related bugs, as well as concurrency issues. Now it works okay, but the thread-shutdown is still an issue, as it causes incorrect behaviour making the tests fail. Its good, as it hints at additional issues that need to be solved. There is just a little more left on the feature side, but its nearly there
161 fbe062bf6dacd3ad63dd827d898337fa542931ac 6d1212e8c412b0b4802bc1080d38d54907db879d Sebastian Thiel <byronimo@gmail.com> 1276249921 +0200 commit: IMPORTANT: sometimes, when notifying waiters by releasing their lock, the lock is not actually released or they are not actually notifyied, staying in a beautysleep. This glitch is probably caused by some detail not treated correctly in the thread python module, which is something we cannot fix. It works most of the time as expected though - maybe some cleanup is not done correctly which causes this
162 6d1212e8c412b0b4802bc1080d38d54907db879d 01eac1a959c1fa5894a86bf11e6b92f96762bdd8 Sebastian Thiel <byronimo@gmail.com> 1276249936 +0200 checkout: moving from channel to taskdep
163 01eac1a959c1fa5894a86bf11e6b92f96762bdd8 18b14ade522c71000a69ff80569eda7335d6f64c Sebastian Thiel <byronimo@gmail.com> 1276249944 +0200 merge channel: Merge made by recursive.
164 18b14ade522c71000a69ff80569eda7335d6f64c 583e6a25b0d891a2f531a81029f2bac0c237cbf9 Sebastian Thiel <byronimo@gmail.com> 1276258825 +0200 commit (amend): Merge branch 'channel' into taskdep
165 583e6a25b0d891a2f531a81029f2bac0c237cbf9 5ff864138cd1e680a78522c26b583639f8f5e313 Sebastian Thiel <byronimo@gmail.com> 1276259871 +0200 commit: test.async: split test_pool up into task implenetations and related utilities, as well as the tests themselves. File became too large
166 5ff864138cd1e680a78522c26b583639f8f5e313 18e3252a1f655f09093a4cffd5125342a8f94f3b Sebastian Thiel <byronimo@gmail.com> 1276261131 +0200 commit: Finished dependent task testing according to the features we would currently like to see
167 18e3252a1f655f09093a4cffd5125342a8f94f3b 257a8a9441fca9a9bc384f673ba86ef5c3f1715d Sebastian Thiel <byronimo@gmail.com> 1276261137 +0200 checkout: moving from taskdep to async
168 257a8a9441fca9a9bc384f673ba86ef5c3f1715d f606937a7a21237c866efafcad33675e6539c103 Sebastian Thiel <byronimo@gmail.com> 1276261142 +0200 merge taskdep: Merge made by recursive.
169 f606937a7a21237c866efafcad33675e6539c103 f606937a7a21237c866efafcad33675e6539c103 Sebastian Thiel <byronimo@gmail.com> 1276261390 +0200 checkout: moving from async to cleanup
170 f606937a7a21237c866efafcad33675e6539c103 02de401bc0b5ab5b97736265b18c7d1d6f53b9c1 Sebastian Thiel <byronimo@gmail.com> 1276266327 +0200 commit: Improved shutdown handling - although its impossible to prevent some stderr printing thanks to the underlying threading implementation, we can at least make sure that the interpreter doesn't block during shutdown. Now it appears to be running smoothly
171 02de401bc0b5ab5b97736265b18c7d1d6f53b9c1 1873db442dc7511fc2c92fbaeb8d998d3e62723d Sebastian Thiel <byronimo@gmail.com> 1276266595 +0200 commit (amend): Improved shutdown handling - although its impossible to prevent some stderr printing thanks to the underlying threading implementation, we can at least make sure that the interpreter doesn't block during shutdown. Now it appears to be running smoothly
172 1873db442dc7511fc2c92fbaeb8d998d3e62723d e14e3f143e7260de9581aee27e5a9b2645db72de Sebastian Thiel <byronimo@gmail.com> 1276267329 +0200 commit: Removed commented-out debug code and additional debug printings. Verified it works on py2.4, 2.5 and 2.6
173 e14e3f143e7260de9581aee27e5a9b2645db72de f606937a7a21237c866efafcad33675e6539c103 Sebastian Thiel <byronimo@gmail.com> 1276267656 +0200 checkout: moving from cleanup to async
174 f606937a7a21237c866efafcad33675e6539c103 29eb123beb1c55e5db4aa652d843adccbd09ae18 Sebastian Thiel <byronimo@gmail.com> 1276267660 +0200 merge cleanup: Merge made by recursive.
175 29eb123beb1c55e5db4aa652d843adccbd09ae18 cac6e06cc9ef2903a15e594186445f3baa989a1a Sebastian Thiel <byronimo@gmail.com> 1276268324 +0200 commit: test_task: fixed import error, made all modules from x import * safe
176 cac6e06cc9ef2903a15e594186445f3baa989a1a a28942bdf01f4ddb9d0b5a0489bd6f4e101dd775 Sebastian Thiel <byronimo@gmail.com> 1276280001 +0200 commit: Added performance test, improved iterator task which will now be usable by default. It shows that there must be the notion of a producer, which can work if there are no items read
177 a28942bdf01f4ddb9d0b5a0489bd6f4e101dd775 9e7fbc06cbcb51efb8c88fedaeb257a435c0c162 Sebastian Thiel <byronimo@gmail.com> 1276334358 +0200 commit: Cleaned up channel design, Reader and Writer bases don't require a channel anymore, but are abstract.
178 9e7fbc06cbcb51efb8c88fedaeb257a435c0c162 be8955a0fbb77d673587974b763f17c214904b57 Sebastian Thiel <byronimo@gmail.com> 1276334369 +0200 commit (amend): Cleaned up channel design, Reader and Writer bases don't require a channel anymore, but are abstract.
179 be8955a0fbb77d673587974b763f17c214904b57 1d8a577ffc6ad7ce1465001ddebdc157aecc1617 Sebastian Thiel <byronimo@gmail.com> 1276335670 +0200 commit: channel: cleaned up inheritance hierarchy, adding mixing for callback functionality - previously the callback functionality was bound to channel based readers/writers
180 1d8a577ffc6ad7ce1465001ddebdc157aecc1617 eded3fb0c820761d51d462e0d96187371c1758dc Sebastian Thiel <byronimo@gmail.com> 1276339082 +0200 commit: task: improved naming of task types, improved pool test to be less dependent on starting with just the main thread
181 eded3fb0c820761d51d462e0d96187371c1758dc 7a0b79ee574999ecbc76696506352e4a5a0d7159 Sebastian Thiel <byronimo@gmail.com> 1276339207 +0200 commit (amend): task: improved naming of task types, improved pool test to be less dependent on starting with just the main thread
182 7a0b79ee574999ecbc76696506352e4a5a0d7159 7c1169f6ea406fec1e26e99821e18e66437e65eb Sebastian Thiel <byronimo@gmail.com> 1276339273 +0200 checkout: moving from async to master
183 7c1169f6ea406fec1e26e99821e18e66437e65eb f91495e271597034226f1b9651345091083172c4 Sebastian Thiel <byronimo@gmail.com> 1276339280 +0200 merge async: Merge made by recursive.
184 f91495e271597034226f1b9651345091083172c4 5c631ca192848fed3068b31b1389cd92a0c0cdca Sebastian Thiel <byronimo@gmail.com> 1276340638 +0200 commit: Removed async from this repository, put it into own one which now comes in as external, using a git-submodule
185 5c631ca192848fed3068b31b1389cd92a0c0cdca f91495e271597034226f1b9651345091083172c4 Sebastian Thiel <byronimo@gmail.com> 1276345979 +0200 HEAD~1: updating HEAD
186 f91495e271597034226f1b9651345091083172c4 86ea63504f3e8a74cfb1d533be9d9602d2d17e27 Sebastian Thiel <byronimo@gmail.com> 1276346049 +0200 commit: Removed async from tree
187 86ea63504f3e8a74cfb1d533be9d9602d2d17e27 6c1faef799095f3990e9970bc2cb10aa0221cf9c Sebastian Thiel <byronimo@gmail.com> 1276356043 +0200 commit: Removed odb from project, it is now used as a submodule named gitdb, which was added instead
188 6c1faef799095f3990e9970bc2cb10aa0221cf9c 28ed48c93f4cc8b6dd23c951363e5bd4e6880992 Sebastian Thiel <byronimo@gmail.com> 1276503381 +0200 commit: Implemented initial version of tree serialization which appears to work according to a simple test
189 28ed48c93f4cc8b6dd23c951363e5bd4e6880992 fe5289ed8311fecf39913ce3ae86b1011eafe5f7 Sebastian Thiel <byronimo@gmail.com> 1276506168 +0200 commit: tree now uses less memory for its cache as it stores the bare deserialized information - this also speeds up later serialization after changes. its clear though that retrieving actual objects is slower currently as these are not cached anymore. Its worth thinking about moving these encoding, decoding routines to gitdb
190 fe5289ed8311fecf39913ce3ae86b1011eafe5f7 f8dabbf4f92a7023181777e9d40355562474f71a Sebastian Thiel <byronimo@gmail.com> 1276512508 +0200 commit: tree: added TreeModifier, allowing to adjust existing trees safely and or fast, while staying compatible with serialization which requires it to be sorted
191 f8dabbf4f92a7023181777e9d40355562474f71a d9240918aa03e49feabe43af619019805ac76786 Sebastian Thiel <byronimo@gmail.com> 1276512707 +0200 commit (amend): tree: added TreeModifier, allowing to adjust existing trees safely and or fast, while staying compatible with serialization which requires it to be sorted
192 d9240918aa03e49feabe43af619019805ac76786 d9240918aa03e49feabe43af619019805ac76786 Sebastian Thiel <byronimo@gmail.com> 1276520481 +0200 checkout: moving from master to index
193 d9240918aa03e49feabe43af619019805ac76786 af32b6e0ad4ab244dc70a5ade0f8a27ab45942f8 Sebastian Thiel <byronimo@gmail.com> 1276524270 +0200 commit: index: split index file into multiple files of a single package. This didn't reduce the file size as much as I would have liked, but certainly is a start for further 'outsourcing'
194 af32b6e0ad4ab244dc70a5ade0f8a27ab45942f8 0ad4af53d4704489f2fd8bd067241bf12c8ee35a Sebastian Thiel <byronimo@gmail.com> 1276525421 +0200 commit: Implemented the serializable interface - by refactoring code
195 0ad4af53d4704489f2fd8bd067241bf12c8ee35a abaefc59a7f2986ab344a65ef2a3653ce7dd339f Sebastian Thiel <byronimo@gmail.com> 1276527582 +0200 commit (amend): Implemented the serializable interface - by refactoring code
196 abaefc59a7f2986ab344a65ef2a3653ce7dd339f d9240918aa03e49feabe43af619019805ac76786 Sebastian Thiel <byronimo@gmail.com> 1276527605 +0200 checkout: moving from index to master
197 d9240918aa03e49feabe43af619019805ac76786 38b3cfb9b24a108e0720f7a3f8d6355f7e0bb1a9 Sebastian Thiel <byronimo@gmail.com> 1276527612 +0200 merge index: Merge made by recursive.
198 38b3cfb9b24a108e0720f7a3f8d6355f7e0bb1a9 c9dbf201b4f0b3c2b299464618cb4ecb624d272c Sebastian Thiel <byronimo@gmail.com> 1276529105 +0200 commit: Moved small types that had their own module into the utils module
199 c9dbf201b4f0b3c2b299464618cb4ecb624d272c 45e87305bd4f050c2d0309c32fe5de499fc38df3 Sebastian Thiel <byronimo@gmail.com> 1276554725 +0200 commit: Reimplemented Lock handling to be conforming to the git lock protocol, which is actually more efficient than the previous implementation
200 45e87305bd4f050c2d0309c32fe5de499fc38df3 06590aee389f4466e02407f39af1674366a74705 Sebastian Thiel <byronimo@gmail.com> 1276555536 +0200 commit (amend): Reimplemented Lock handling to be conforming to the git lock protocol, which is actually more efficient than the previous implementation
201 06590aee389f4466e02407f39af1674366a74705 1d2307532d679393ae067326e4b6fa1a2ba5cc06 Sebastian Thiel <byronimo@gmail.com> 1276556905 +0200 commit: Moved LockedFD and its test into the gitdb project
202 1d2307532d679393ae067326e4b6fa1a2ba5cc06 e837b901dcfac82e864f806c80f4a9cbfdb9c9f3 Sebastian Thiel <byronimo@gmail.com> 1276607908 +0200 commit: Move LazyMixin type to gitdb, index reading now uses file_contents_ro from gitdb as well
203 e837b901dcfac82e864f806c80f4a9cbfdb9c9f3 b82dbf538ac0d03968a0f5b7e2318891abefafaa Sebastian Thiel <byronimo@gmail.com> 1276870827 +0200 commit: GitCmd implementation of gitdb base moved to git-python where it belongs. Previously it was located in gitdb, which doesn't have any facilities to use the git command
204 b82dbf538ac0d03968a0f5b7e2318891abefafaa f164627a85ed7b816759871a76db258515b85678 Sebastian Thiel <byronimo@gmail.com> 1277057845 +0200 commit: db: added pure python git database
205 f164627a85ed7b816759871a76db258515b85678 ac62760c52abf28d1fd863f0c0dd48bc4a23d223 Sebastian Thiel <byronimo@gmail.com> 1277117506 +0200 commit: index.add: now uses gitdb.store functionality instead of git-hash-file. The python version is about as fast, but could support multithreading using async
206 ac62760c52abf28d1fd863f0c0dd48bc4a23d223 0fdf6c3aaff49494c47aaeb0caa04b3016e10a26 Sebastian Thiel <byronimo@gmail.com> 1277127929 +0200 commit: index: Entries are now using flags internally, instead of reducing the flag information to just the stage ( just to be closer to the git-original )
207 0fdf6c3aaff49494c47aaeb0caa04b3016e10a26 0aeb491d3d8f53e07fb21f36251be4880170c5ab Sebastian Thiel <byronimo@gmail.com> 1277129321 +0200 commit: index.add does not need the git clt anymore
208 0aeb491d3d8f53e07fb21f36251be4880170c5ab 91725f0fc59aa05ef68ab96e9b29009ce84668a5 Sebastian Thiel <byronimo@gmail.com> 1277129385 +0200 commit (amend): index.add does not need the git clt anymore
209 91725f0fc59aa05ef68ab96e9b29009ce84668a5 91725f0fc59aa05ef68ab96e9b29009ce84668a5 Sebastian Thiel <byronimo@gmail.com> 1277132483 +0200 checkout: moving from master to writetree
210 91725f0fc59aa05ef68ab96e9b29009ce84668a5 1044116d25f0311033e0951d2ab30579bba4b051 Sebastian Thiel <byronimo@gmail.com> 1277144182 +0200 commit: index: put serialization methods into new 'fun' module, this makes the calls faster as it removes one level of indirection, and makes the main file smaller, improving maintainability
211 1044116d25f0311033e0951d2ab30579bba4b051 69dd8750be1fbf55010a738dc1ced4655e727f23 Sebastian Thiel <byronimo@gmail.com> 1277157937 +0200 commit: index.write_tree: initial version implemented, although its not yet working correctly, a test to explicitly compare the git version with the python implementation is still missing
212 69dd8750be1fbf55010a738dc1ced4655e727f23 cadce432d8ef07e7293f8b760342d717bd350671 Sebastian Thiel <byronimo@gmail.com> 1277188932 +0200 commit: intermediate commit, rollback
213 cadce432d8ef07e7293f8b760342d717bd350671 69dd8750be1fbf55010a738dc1ced4655e727f23 Sebastian Thiel <byronimo@gmail.com> 1277189427 +0200 HEAD~1: updating HEAD
214 69dd8750be1fbf55010a738dc1ced4655e727f23 d2d9197cfe5d3b43cb8aee182b2e65c73ef9ab7b Sebastian Thiel <byronimo@gmail.com> 1277193172 +0200 commit: Tree-Writing now works after fixing an off-by-one error
215 d2d9197cfe5d3b43cb8aee182b2e65c73ef9ab7b c4f49fb232acb2c02761a82acc12c4040699685d Sebastian Thiel <byronimo@gmail.com> 1277201017 +0200 commit: index.write_tree: now uses MemoryDB, making tree handling more efficient as IO will only be done when required. A possible disadvantage though is that time is spent on compressing the trees, although only the raw data and their shas would theoretically be needed. On the other hand, compressing their data uses less memory. An optimal implementation would just sha the data, check for existance, and compress it to write it to the database right away. This would mean more specialized code though, introducing redundancy. If IStreams would know whether they contain compressed or uncompressed data, and if there was a method to get a sha from data, this would work nicely in the existing framework though
216 c4f49fb232acb2c02761a82acc12c4040699685d 91725f0fc59aa05ef68ab96e9b29009ce84668a5 Sebastian Thiel <byronimo@gmail.com> 1277201030 +0200 checkout: moving from writetree to master
217 91725f0fc59aa05ef68ab96e9b29009ce84668a5 778234d544b3f58dd415aaf10679d15b01a5281f Sebastian Thiel <byronimo@gmail.com> 1277201033 +0200 merge writetree: Merge made by recursive.
218 778234d544b3f58dd415aaf10679d15b01a5281f 778234d544b3f58dd415aaf10679d15b01a5281f Sebastian Thiel <byronimo@gmail.com> 1277209257 +0200 checkout: moving from master to fromtree
219 778234d544b3f58dd415aaf10679d15b01a5281f be97c4558992a437cde235aafc7ae2bd6df84ac8 Sebastian Thiel <byronimo@gmail.com> 1277234627 +0200 commit: Initial frame for implementing read_tree using pure python. As git-read-tree can do much more than we can ( and faster assumably ), the .new method is used to create new index instances from up to 3 trees.
220 be97c4558992a437cde235aafc7ae2bd6df84ac8 c0ef65b43688b1a4615a1e7332f6215f9a8abb19 Sebastian Thiel <byronimo@gmail.com> 1277245716 +0200 commit: Implemented simple tree merging and a simple test, more elaborate testing is in progress
221 c0ef65b43688b1a4615a1e7332f6215f9a8abb19 aea0243840a46021e6f77c759c960a06151d91c9 Sebastian Thiel <byronimo@gmail.com> 1277293745 +0200 commit: Added test for aggressive_tree_merge
222 aea0243840a46021e6f77c759c960a06151d91c9 1e2265a23ecec4e4d9ad60d788462e7f124f1bb7 Sebastian Thiel <byronimo@gmail.com> 1277300937 +0200 commit: fixed critical bug in traverse_trees_recursive, implemented IndexFile.new including simple test, it may be simple as the methods it uses are throroughly tested
223 1e2265a23ecec4e4d9ad60d788462e7f124f1bb7 778234d544b3f58dd415aaf10679d15b01a5281f Sebastian Thiel <byronimo@gmail.com> 1277300988 +0200 checkout: moving from fromtree to master
224 778234d544b3f58dd415aaf10679d15b01a5281f 57050184f3d962bf91511271af59ee20f3686c3f Sebastian Thiel <byronimo@gmail.com> 1277301014 +0200 merge fromtree: Merge made by recursive.
225 57050184f3d962bf91511271af59ee20f3686c3f 129f90aa8d83d9b250c87b0ba790605c4a2bb06a Sebastian Thiel <byronimo@gmail.com> 1277334478 +0200 commit: Multiple partly critical bugfixes related to index handling
226 129f90aa8d83d9b250c87b0ba790605c4a2bb06a a1adb421c2ee3e4868ea70d440dd82896219ed8f Sebastian Thiel <byronimo@gmail.com> 1277388148 +0200 commit: aggressive_tree_merge: fixed incorrect handling of one branch, it was just not implemented causing incorrect merge results. Added test to cover this issue
227 a1adb421c2ee3e4868ea70d440dd82896219ed8f 55dcc17c331f580b3beeb4d5decf64d3baf94f2e Sebastian Thiel <byronimo@gmail.com> 1277395720 +0200 commit (amend): aggressive_tree_merge: fixed incorrect handling of one branch, it was just not implemented causing incorrect merge results. Added test to cover this issue
228 55dcc17c331f580b3beeb4d5decf64d3baf94f2e ca131dd61e26f46f49ee3f70763f994cf9512665 Sebastian Thiel <byronimo@gmail.com> 1277401303 +0200 commit: GitCmdStreamReader: fixed terrible bug which only kicked in if the stream was actually empty. This is a rare case that can happen during stream testing. Theoretically there shouldn't be any empty streams of course, but practically they do exist sometimes ;)
229 ca131dd61e26f46f49ee3f70763f994cf9512665 feb1ea0f4aacb9ea6dc4133900e65bf34c0ee02d Sebastian Thiel <byronimo@gmail.com> 1277401306 +0200 commit (amend): GitCmdStreamReader: fixed terrible bug which only kicked in if the stream was actually empty. This is a rare case that can happen during stream testing. Theoretically there shouldn't be any empty streams of course, but practically they do exist sometimes ;); fixed stream.seek implementation, which previously used seek on standard output
230 feb1ea0f4aacb9ea6dc4133900e65bf34c0ee02d 402a6c2808db4333217aa300d0312836fd7923bd Sebastian Thiel <byronimo@gmail.com> 1277407147 +0200 commit: IndexFile.add: writing of the index file can now optionally be turned off. The default is to write the physical index, which is the behaviour you would expect
231 402a6c2808db4333217aa300d0312836fd7923bd 402a6c2808db4333217aa300d0312836fd7923bd Sebastian Thiel <byronimo@gmail.com> 1277417929 +0200 checkout: moving from master to index
232 402a6c2808db4333217aa300d0312836fd7923bd 4d30dfb07f78517b1ba20b88506e01678edd527c Sebastian Thiel <byronimo@gmail.com> 1277417979 +0200 commit: index.reset is now partly implemented using python, but in fact it resorts to using git-read-tree to keep the stat information when merging one tree in. After all this is what needed to be implemented in python as well
233 4d30dfb07f78517b1ba20b88506e01678edd527c 58fb1187b7b8f1e62d3930bdba9be5aba47a52c6 Sebastian Thiel <byronimo@gmail.com> 1277473186 +0200 commit (amend): index.reset is now partly implemented using python, but in fact it resorts to using git-read-tree to keep the stat information when merging one tree in. After all this is what needed to be implemented in python as well
234 58fb1187b7b8f1e62d3930bdba9be5aba47a52c6 402a6c2808db4333217aa300d0312836fd7923bd Sebastian Thiel <byronimo@gmail.com> 1277473192 +0200 checkout: moving from index to master
235 402a6c2808db4333217aa300d0312836fd7923bd 58fb1187b7b8f1e62d3930bdba9be5aba47a52c6 Sebastian Thiel <byronimo@gmail.com> 1277473196 +0200 merge index: Fast-forward
236 58fb1187b7b8f1e62d3930bdba9be5aba47a52c6 58fb1187b7b8f1e62d3930bdba9be5aba47a52c6 Sebastian Thiel <byronimo@gmail.com> 1277473218 +0200 checkout: moving from master to sha20
237 58fb1187b7b8f1e62d3930bdba9be5aba47a52c6 47e3138ee978ce708a41f38a0d874376d7ae5c78 Sebastian Thiel <byronimo@gmail.com> 1277503104 +0200 commit: Adjusted all files to (hopefully) deal with the fact that all objects now use 20 byte sha's internally as it is closer to the GitDB implementation
238 47e3138ee978ce708a41f38a0d874376d7ae5c78 7abe9065aab9dec56015ede5f2b0082837c5dc2e Sebastian Thiel <byronimo@gmail.com> 1277745342 +0200 commit: All tests adjusted to work with the changed internal sha representation
239 7abe9065aab9dec56015ede5f2b0082837c5dc2e 1fe889ea0cb2547584075dc1eb77f52c54b9a8c4 Sebastian Thiel <byronimo@gmail.com> 1277745354 +0200 commit (amend): All tests adjusted to work with the changed internal sha representation
240 1fe889ea0cb2547584075dc1eb77f52c54b9a8c4 58fb1187b7b8f1e62d3930bdba9be5aba47a52c6 Sebastian Thiel <byronimo@gmail.com> 1277745377 +0200 checkout: moving from sha20 to master
241 58fb1187b7b8f1e62d3930bdba9be5aba47a52c6 8d2239f24f6a54d98201413d4f46256df0d6a5f3 Sebastian Thiel <byronimo@gmail.com> 1277745383 +0200 merge sha20: Merge made by recursive.
242 8d2239f24f6a54d98201413d4f46256df0d6a5f3 f1401803ccf7db5d897a5ef4b27e2176627c430e Sebastian Thiel <byronimo@gmail.com> 1277756712 +0200 commit: Fixed performance tests which broke in the course of the sha1-20 byte changes
243 f1401803ccf7db5d897a5ef4b27e2176627c430e 6917ae4ce9eaa0f5ea91592988c1ea830626ac3a Sebastian Thiel <byronimo@gmail.com> 1277806256 +0200 commit: Diff: fixed bug that caused a string to end up as a blob mode
244 6917ae4ce9eaa0f5ea91592988c1ea830626ac3a 6917ae4ce9eaa0f5ea91592988c1ea830626ac3a Sebastian Thiel <byronimo@gmail.com> 1277819766 +0200 checkout: moving from master to docs
245 6917ae4ce9eaa0f5ea91592988c1ea830626ac3a 160081b9a7ca191afbec077c4bf970cfd9070d2c Sebastian Thiel <byronimo@gmail.com> 1277828911 +0200 commit: Updated and fixed sphinx API docs, which included one quick skim-through
246 160081b9a7ca191afbec077c4bf970cfd9070d2c 791765c0dc2d00a9ffa4bc857d09f615cfe3a759 Sebastian Thiel <byronimo@gmail.com> 1277830741 +0200 commit: Removed repo tests which for some reason left the 'repos' directory around, replaced them by a real test which actually executes code, and puts everything into the tmp directory
247 791765c0dc2d00a9ffa4bc857d09f615cfe3a759 77cd6659b64cb1950a82e6a3cccdda94f15ae739 Sebastian Thiel <byronimo@gmail.com> 1277834446 +0200 commit: Renamed modules utils to util, and errors to exc to be more conforming to the submodules's naming conventions
248 77cd6659b64cb1950a82e6a3cccdda94f15ae739 18be0972304dc7f1a2a509595de7da689bddbefa Sebastian Thiel <byronimo@gmail.com> 1277835397 +0200 commit: Removed blob.data property as there is no real reason for an exception to the rule of trying not to cache possibly heavy data. The data_stream method should be used instead
249 18be0972304dc7f1a2a509595de7da689bddbefa 0369384c8b79c44c5369f1b6c05046899f8886da Sebastian Thiel <byronimo@gmail.com> 1277840971 +0200 commit: revised tutorial to match the changed usage, added basic information about object databases
250 0369384c8b79c44c5369f1b6c05046899f8886da ee58d55133c571db6384acf916e4a1c3592be07b Sebastian Thiel <byronimo@gmail.com> 1277848046 +0200 commit: Added whatsnew and put it into the index
251 ee58d55133c571db6384acf916e4a1c3592be07b 77d083040248deeccb3ac1ad125eb2969b5cb370 Sebastian Thiel <byronimo@gmail.com> 1277848184 +0200 commit (amend): Added whatsnew and put it into the index
252 77d083040248deeccb3ac1ad125eb2969b5cb370 fde6522c40a346c8b1d588a2b8d4dd362ae1f58f Sebastian Thiel <byronimo@gmail.com> 1277848539 +0200 commit (amend): Added whatsnew and put it into the index
253 fde6522c40a346c8b1d588a2b8d4dd362ae1f58f 28a33ca17ac5e0816a3e24febb47ffcefa663980 Sebastian Thiel <byronimo@gmail.com> 1277991925 +0200 commit: Added further information about the required submodules, and how to install them. Incremeneted version to 0.3.0 beta1
254 28a33ca17ac5e0816a3e24febb47ffcefa663980 586aa65f772f69eb6d08224968c74dda1ca45612 Sebastian Thiel <byronimo@gmail.com> 1277993503 +0200 commit: Moved all source files into the source folder, separating the build from the source directory
255 586aa65f772f69eb6d08224968c74dda1ca45612 d2ebc6193f7205fd1686678a5707262cb1c59bb0 Sebastian Thiel <byronimo@gmail.com> 1277993585 +0200 commit (amend): Moved all source files into the source folder, separating the build from the source directory
256 d2ebc6193f7205fd1686678a5707262cb1c59bb0 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af Sebastian Thiel <byronimo@gmail.com> 1277994361 +0200 checkout: moving from docs to hub/0.2
257 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af 7bfca5efce8988e6070e7284bd409d1a731a3fbc Sebastian Thiel <byronimo@gmail.com> 1277994419 +0200 checkout: moving from 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af to hub/0.1
258 7bfca5efce8988e6070e7284bd409d1a731a3fbc d2ebc6193f7205fd1686678a5707262cb1c59bb0 Sebastian Thiel <byronimo@gmail.com> 1277994469 +0200 checkout: moving from 7bfca5efce8988e6070e7284bd409d1a731a3fbc to docs
259 d2ebc6193f7205fd1686678a5707262cb1c59bb0 c3bd05b426a0e3dec8224244c3c9c0431d1ff130 Sebastian Thiel <byronimo@gmail.com> 1277994911 +0200 commit: Added doc-index, which helps to keep documentation of prior but still somewhat supported versions alive
260 c3bd05b426a0e3dec8224244c3c9c0431d1ff130 6917ae4ce9eaa0f5ea91592988c1ea830626ac3a Sebastian Thiel <byronimo@gmail.com> 1277999895 +0200 checkout: moving from docs to master
261 6917ae4ce9eaa0f5ea91592988c1ea830626ac3a fd96cceded27d1372bdc1a851448d2d8613f60f3 Sebastian Thiel <byronimo@gmail.com> 1277999899 +0200 merge docs: Merge made by recursive.
262 fd96cceded27d1372bdc1a851448d2d8613f60f3 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af Sebastian Thiel <byronimo@gmail.com> 1278082024 +0200 checkout: moving from master to 0.2.0-beta1
263 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af fd96cceded27d1372bdc1a851448d2d8613f60f3 Sebastian Thiel <byronimo@gmail.com> 1278082288 +0200 checkout: moving from 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af to master
264 fd96cceded27d1372bdc1a851448d2d8613f60f3 f683c6623f73252645bb2819673046c9d397c567 Sebastian Thiel <byronimo@gmail.com> 1278082451 +0200 commit: Fixed broken 0.2 documentation, it didn't contain the API reference previously due to import errors and a somewhat inconsistent working tree that occurred when switching branches ...
265 f683c6623f73252645bb2819673046c9d397c567 a4287f65878000b42d11704692f9ea3734014b4c Sebastian Thiel <byronimo@gmail.com> 1278092317 +0200 commit: win32 compatability adjustments
266 a4287f65878000b42d11704692f9ea3734014b4c a4287f65878000b42d11704692f9ea3734014b4c Sebastian Thiel <byronimo@gmail.com> 1278315351 +0200 checkout: moving from master to revparse
267 a4287f65878000b42d11704692f9ea3734014b4c f963881e53a9f0a2746a11cb9cdfa82eb1f90d8c Sebastian Thiel <byronimo@gmail.com> 1278369330 +0200 commit: Initial version of the rev-parse routine, which doesn't work too bad, but its still rather slow and many tests are not yet implemented
268 f963881e53a9f0a2746a11cb9cdfa82eb1f90d8c 1c6d7830d9b87f47a0bfe82b3b5424a32e3164ad Sebastian Thiel <byronimo@gmail.com> 1278405962 +0200 commit: RevParse now generally works, but there are still some more specialized tests missing
269 1c6d7830d9b87f47a0bfe82b3b5424a32e3164ad a32a6bcd784fca9cb2b17365591c29d15c2f638e Sebastian Thiel <byronimo@gmail.com> 1278407809 +0200 commit: Refs now use object.new_from_sha where possible, preventing git-batch-check to be started up for sha resolution
270 a32a6bcd784fca9cb2b17365591c29d15c2f638e 355aa879cff8630c9eedaf151f90a229f2ba5135 Sebastian Thiel <byronimo@gmail.com> 1278410951 +0200 commit: Implemented main rev-parsing, including long hexshas, tags and refs. Short Shas still to be done
271 355aa879cff8630c9eedaf151f90a229f2ba5135 73959f3a2d4f224fbda03c8a8850f66f53d8cb3b Sebastian Thiel <byronimo@gmail.com> 1278418771 +0200 commit (amend): Implemented main rev-parsing, including long hexshas, tags and refs. Short Shas still to be done
272 73959f3a2d4f224fbda03c8a8850f66f53d8cb3b 9059525a75b91e6eb6a425f1edcc608739727168 Sebastian Thiel <byronimo@gmail.com> 1278440512 +0200 commit: Made repo.py a package to allow better localization of functions and utilities - the repo module got rather large
273 9059525a75b91e6eb6a425f1edcc608739727168 f068cdc5a1a13539c4a1d756ae950aab65f5348b Sebastian Thiel <byronimo@gmail.com> 1278497773 +0200 commit: Initially working implementation of short-sha parsing and interpretation, thanks to new gitdb functionality
274 f068cdc5a1a13539c4a1d756ae950aab65f5348b bc31651674648f026464fd4110858c4ffeac3c18 Sebastian Thiel <byronimo@gmail.com> 1278516647 +0200 commit: Adjusted previous object creators to use the rev_parse method directly. rev_parse could be adjusted not to return Objects anymore, providing better performance for those who just want a sha only. On the other hand, the method is high-level and should be convenient to use as well, its a starting point for more usually, hence its unlikely to call it in tight loops
275 bc31651674648f026464fd4110858c4ffeac3c18 8a73805d9b26b5a6c54f2e8d53f948df7db8b3d4 Sebastian Thiel <byronimo@gmail.com> 1278517362 +0200 commit: Added test for GitCmdObjectDB in order to verify the method is working as expected with different input
276 8a73805d9b26b5a6c54f2e8d53f948df7db8b3d4 01ab5b96e68657892695c99a93ef909165456689 Sebastian Thiel <byronimo@gmail.com> 1278517373 +0200 commit (amend): Added test for GitCmdObjectDB in order to verify the partial_to_complete_sha_hex is working as expected with different input ( it wasn't, of course ;) )
277 01ab5b96e68657892695c99a93ef909165456689 a4287f65878000b42d11704692f9ea3734014b4c Sebastian Thiel <byronimo@gmail.com> 1278517411 +0200 checkout: moving from revparse to master
278 a4287f65878000b42d11704692f9ea3734014b4c ca288d443f4fc9d790eecb6e1cdf82b6cdd8dc0d Sebastian Thiel <byronimo@gmail.com> 1278517416 +0200 merge revparse: Merge made by recursive.
279 ca288d443f4fc9d790eecb6e1cdf82b6cdd8dc0d a4287f65878000b42d11704692f9ea3734014b4c Sebastian Thiel <byronimo@gmail.com> 1278525786 +0200 checkout: moving from master to master~1
280 a4287f65878000b42d11704692f9ea3734014b4c ca288d443f4fc9d790eecb6e1cdf82b6cdd8dc0d Sebastian Thiel <byronimo@gmail.com> 1278525793 +0200 checkout: moving from a4287f65878000b42d11704692f9ea3734014b4c to master
281 ca288d443f4fc9d790eecb6e1cdf82b6cdd8dc0d 01ab5b96e68657892695c99a93ef909165456689 Sebastian Thiel <byronimo@gmail.com> 1278525803 +0200 checkout: moving from master to master^2
282 01ab5b96e68657892695c99a93ef909165456689 bc31651674648f026464fd4110858c4ffeac3c18 Sebastian Thiel <byronimo@gmail.com> 1278525815 +0200 checkout: moving from 01ab5b96e68657892695c99a93ef909165456689 to master^2~1
283 bc31651674648f026464fd4110858c4ffeac3c18 f068cdc5a1a13539c4a1d756ae950aab65f5348b Sebastian Thiel <byronimo@gmail.com> 1278525821 +0200 checkout: moving from bc31651674648f026464fd4110858c4ffeac3c18 to master^2~2
284 f068cdc5a1a13539c4a1d756ae950aab65f5348b 73959f3a2d4f224fbda03c8a8850f66f53d8cb3b Sebastian Thiel <byronimo@gmail.com> 1278525826 +0200 checkout: moving from f068cdc5a1a13539c4a1d756ae950aab65f5348b to master^2~4
285 73959f3a2d4f224fbda03c8a8850f66f53d8cb3b ca288d443f4fc9d790eecb6e1cdf82b6cdd8dc0d Sebastian Thiel <byronimo@gmail.com> 1278525829 +0200 checkout: moving from 73959f3a2d4f224fbda03c8a8850f66f53d8cb3b to master
286 ca288d443f4fc9d790eecb6e1cdf82b6cdd8dc0d 5fd6cc37fd07c25cb921b77b4f658b7e8fc132b3 Sebastian Thiel <byronimo@gmail.com> 1278536545 +0200 commit: Adjusted clone method to allow static classmethod clone ( using clone_from ) as well as the previous instance method clone to keep it compatible
287 5fd6cc37fd07c25cb921b77b4f658b7e8fc132b3 76af62b3c5a26638fcad9a3fe401fba566fb7037 Sebastian Thiel <byronimo@gmail.com> 1278538933 +0200 commit (amend): Adjusted clone method to allow static classmethod clone ( using clone_from ) as well as the previous instance method clone to keep it compatible
288 76af62b3c5a26638fcad9a3fe401fba566fb7037 b425301ad16f265157abdaf47f7af1c1ea879068 Sebastian Thiel <byronimo@gmail.com> 1278539147 +0200 commit (amend): Adjusted clone method to allow static classmethod clone ( using clone_from ) as well as the previous instance method clone to keep it compatible
289 b425301ad16f265157abdaf47f7af1c1ea879068 3288a244428751208394d8137437878277ceb71f Sebastian Thiel <byronimo@gmail.com> 1278582561 +0200 commit: setup.py: fixed requirement - its interesting to see that there are two different keywords for distutils and setuptools, the latter one doesn't read the ones of the first one, unfortunately
290 3288a244428751208394d8137437878277ceb71f 08457a7a6b6ad4f518fad0d5bca094a2b5b38fbe Sebastian Thiel <byronimo@gmail.com> 1278670718 +0200 commit: Added python 2.4 support: Repo will now use the original GitCmdObjectDB in python 2.4, as the pure python implementation cannot work without memory maps
291 08457a7a6b6ad4f518fad0d5bca094a2b5b38fbe 258403da9c2a087b10082d26466528fce3de38d4 Sebastian Thiel <byronimo@gmail.com> 1278671744 +0200 commit: bumped verison to 0.3.0 beta2
292 258403da9c2a087b10082d26466528fce3de38d4 55b67e8194b8b4d9e73e27feadbf9af6593e4600 Sebastian Thiel <byronimo@gmail.com> 1278927490 +0200 pull gitorious master: Fast-forward
293 55b67e8194b8b4d9e73e27feadbf9af6593e4600 bcd37b68533d0cceb7e73dd1ed1428fa09f7dc17 Sebastian Thiel <byronimo@gmail.com> 1279007300 +0200 commit: Fixed incorrect use of Blob.data in performance test
294 bcd37b68533d0cceb7e73dd1ed1428fa09f7dc17 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 Sebastian Thiel <byronimo@gmail.com> 1279110447 +0200 commit: Added performance test to compare inst.__class__() vs type(inst)() class. The first one is faster, although I would have expected the latter one to be faster
295 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 Sebastian Thiel <byronimo@gmail.com> 1279130572 +0200 checkout: moving from master to integration
296 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 2603363b435a695f9bf1bbbd5c1c59c353ec0450 Sebastian Thiel <byronimo@gmail.com> 1279130575 +0200 pull git://gitorious.org/git-python/mainline.git refs/merge-requests/2104: Merge made by recursive.
297 2603363b435a695f9bf1bbbd5c1c59c353ec0450 c9c8d48a42d45d22a120e2191ae2f838483caccc Sebastian Thiel <byronimo@gmail.com> 1279130613 +0200 HEAD^2: updating HEAD
298 c9c8d48a42d45d22a120e2191ae2f838483caccc 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 Sebastian Thiel <byronimo@gmail.com> 1279130629 +0200 checkout: moving from integration to master
299 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 a64c5f23c38f06c37a0ca64796368019dfb0d818 Sebastian Thiel <byronimo@gmail.com> 1279130658 +0200 commit: Correct Repo documentation in API reference
300 a64c5f23c38f06c37a0ca64796368019dfb0d818 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 Sebastian Thiel <byronimo@gmail.com> 1279130719 +0200 HEAD~1: updating HEAD
301 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 17a172920fde8c6688c8a1a39f258629b8b73757 Sebastian Thiel <byronimo@gmail.com> 1279131269 +0200 commit: Fixed the missing Repo type documentation thanks to a hint of gasche, fixed a few more resT syntax errors on the way
302 17a172920fde8c6688c8a1a39f258629b8b73757 cbb58869063fe803d232f099888fe9c23510de7b Sebastian Thiel <byronimo@gmail.com> 1279197254 +0200 merge gitorious/master: Fast-forward
303 cbb58869063fe803d232f099888fe9c23510de7b 89422841e46efa99bda49acfbe33ee1ca5122845 Sebastian Thiel <byronimo@gmail.com> 1279533542 +0200 pull gitorious master: Fast-forward
304 89422841e46efa99bda49acfbe33ee1ca5122845 192472f9673b18c91ce618e64e935f91769c50e7 Sebastian Thiel <byronimo@gmail.com> 1279814094 +0200 merge gitorious/master: Fast-forward
305 192472f9673b18c91ce618e64e935f91769c50e7 fa3fce80aeb57299633535b9e1c9d08db710ff05 Sebastian Thiel <byronimo@gmail.com> 1281701051 +0200 commit: unicode handling in messages and trees was improved. Messages are now written according to the encoding of the commit object, and decoded using that information as well. Trees will encode and decode their names with utf8
306 fa3fce80aeb57299633535b9e1c9d08db710ff05 394ed7006ee5dc8bddfd132b64001d5dfc0ffdd3 Sebastian Thiel <byronimo@gmail.com> 1281702078 +0200 commit (amend): unicode handling in messages and trees was improved. Messages are now written according to the encoding of the commit object, and decoded using that information as well. Trees will encode and decode their names with utf8
307 394ed7006ee5dc8bddfd132b64001d5dfc0ffdd3 394ed7006ee5dc8bddfd132b64001d5dfc0ffdd3 Sebastian Thiel <byronimo@gmail.com> 1283969667 +0200 checkout: moving from master to integration
308 394ed7006ee5dc8bddfd132b64001d5dfc0ffdd3 c4d5caa79e6d88bb3f98bfbefa3bfa039c7e157a Sebastian Thiel <byronimo@gmail.com> 1283969669 +0200 pull git://gitorious.org/git-python/mainline.git refs/merge-requests/14: Fast-forward
309 c4d5caa79e6d88bb3f98bfbefa3bfa039c7e157a 394ed7006ee5dc8bddfd132b64001d5dfc0ffdd3 Sebastian Thiel <byronimo@gmail.com> 1283969687 +0200 checkout: moving from integration to master
310 394ed7006ee5dc8bddfd132b64001d5dfc0ffdd3 c4d5caa79e6d88bb3f98bfbefa3bfa039c7e157a Sebastian Thiel <byronimo@gmail.com> 1283969691 +0200 merge integration: Fast-forward
311 c4d5caa79e6d88bb3f98bfbefa3bfa039c7e157a 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a Sebastian Thiel <byronimo@gmail.com> 1287134990 +0200 commit: Fixed bug in http://byronimo.lighthouseapp.com/projects/51787/tickets/44-remoteref-fails-when-there-is-character-in-the-name using supplied patch ( which was manually applied ).
312 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a fc650aa6869639548435ce2760d42c9cdd909d99 Sebastian Thiel <byronimo@gmail.com> 1287135891 +0200 commit: Added test to verify the actor class can handle unicode names correctly. This works because regex can handle unicode, and will return unicode instances instead of strings if required. Its quite amazing actually.
313 fc650aa6869639548435ce2760d42c9cdd909d99 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a Sebastian Thiel <byronimo@gmail.com> 1287136504 +0200 HEAD~1: updating HEAD
314 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a Sebastian Thiel <byronimo@gmail.com> 1287136515 +0200 checkout: moving from master to unicode
315 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a 0f88fb96869b6ac3ed4dac7d23310a9327d3c89c Sebastian Thiel <byronimo@gmail.com> 1287136588 +0200 commit: Added test to verify the actor type can handle and parse unicode if it is passed in
316 0f88fb96869b6ac3ed4dac7d23310a9327d3c89c d39889bcac1735e429ac640ac6838d0e56835afb Sebastian Thiel <byronimo@gmail.com> 1287138883 +0200 commit: Added unicode handling for author names. They will now be properly encoded into the byte stream, as well as decoded from it
317 d39889bcac1735e429ac640ac6838d0e56835afb 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a Sebastian Thiel <byronimo@gmail.com> 1287138889 +0200 checkout: moving from unicode to master
318 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a a88173281ec56cb378a293d0170e11a1bda96a55 Sebastian Thiel <byronimo@gmail.com> 1287138898 +0200 merge unicode: Merge made by recursive.
319 a88173281ec56cb378a293d0170e11a1bda96a55 d39889bcac1735e429ac640ac6838d0e56835afb Sebastian Thiel <byronimo@gmail.com> 1287139063 +0200 checkout: moving from master to unicode
320 d39889bcac1735e429ac640ac6838d0e56835afb a88173281ec56cb378a293d0170e11a1bda96a55 Sebastian Thiel <byronimo@gmail.com> 1287139078 +0200 checkout: moving from unicode to master
321 a88173281ec56cb378a293d0170e11a1bda96a55 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a Sebastian Thiel <byronimo@gmail.com> 1287139082 +0200 HEAD~1: updating HEAD
322 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a d39889bcac1735e429ac640ac6838d0e56835afb Sebastian Thiel <byronimo@gmail.com> 1287139092 +0200 checkout: moving from master to unicode
323 d39889bcac1735e429ac640ac6838d0e56835afb 0019d7dc8c72839d238065473a62b137c3c350f5 Sebastian Thiel <byronimo@gmail.com> 1287139239 +0200 commit (amend): Added unicode handling for author names. They will now be properly encoded into the byte stream, as well as decoded from it
324 0019d7dc8c72839d238065473a62b137c3c350f5 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a Sebastian Thiel <byronimo@gmail.com> 1287139252 +0200 checkout: moving from unicode to master
325 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a 13647590f96fb5a22cb60f12c5a70e00065a7f3a Sebastian Thiel <byronimo@gmail.com> 1287139254 +0200 merge unicode: Merge made by recursive.
326 13647590f96fb5a22cb60f12c5a70e00065a7f3a 94029ce1420ced83c3e5dcd181a2280b26574bc9 Sebastian Thiel <byronimo@gmail.com> 1287139994 +0200 commit: Adjusted regex to support whitespace - it was a little restrictive previously, although there was absolutely no need for that.
327 94029ce1420ced83c3e5dcd181a2280b26574bc9 cfd2121eda5fadd18fba6819f90efb8868fad14a Sebastian Thiel <byronimo@gmail.com> 1287729183 +0200 checkout: moving from master to dotsenko/stable
328 cfd2121eda5fadd18fba6819f90efb8868fad14a 7bfca5efce8988e6070e7284bd409d1a731a3fbc Sebastian Thiel <byronimo@gmail.com> 1287729293 +0200 checkout: moving from cfd2121eda5fadd18fba6819f90efb8868fad14a to HEAD~1
329 7bfca5efce8988e6070e7284bd409d1a731a3fbc 94029ce1420ced83c3e5dcd181a2280b26574bc9 Sebastian Thiel <byronimo@gmail.com> 1287729331 +0200 checkout: moving from 7bfca5efce8988e6070e7284bd409d1a731a3fbc to master
330 94029ce1420ced83c3e5dcd181a2280b26574bc9 8858a63cb33319f3e739edcbfafdae3ec0fefa33 Sebastian Thiel <byronimo@gmail.com> 1288000691 +0200 commit: .gitignore will now ignore netbeans projects
331 8858a63cb33319f3e739edcbfafdae3ec0fefa33 a2b9ded87baf0f32ae94c10c5851a0468a45f003 Sebastian Thiel <byronimo@gmail.com> 1288198935 +0200 commit: docs: untracked_files is a property, but was used like a function, see http://groups.google.com/group/git-python/browse_thread/thread/84ed1835e26a5296?hl=en
332 a2b9ded87baf0f32ae94c10c5851a0468a45f003 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af Sebastian Thiel <byronimo@gmail.com> 1288198941 +0200 checkout: moving from master to 0.2.0-beta1
333 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af a2b9ded87baf0f32ae94c10c5851a0468a45f003 Sebastian Thiel <byronimo@gmail.com> 1288198964 +0200 checkout: moving from 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af to master
334 a2b9ded87baf0f32ae94c10c5851a0468a45f003 8858a63cb33319f3e739edcbfafdae3ec0fefa33 Sebastian Thiel <byronimo@gmail.com> 1288198984 +0200 HEAD~1: updating HEAD
335 8858a63cb33319f3e739edcbfafdae3ec0fefa33 148eb761aeaa4c3913e1766db0a7df0a5b5c8b20 Sebastian Thiel <byronimo@gmail.com> 1288198991 +0200 commit: docs: untracked_files is a property, but was used like a function, see http://groups.google.com/group/git-python/browse_thread/thread/84ed1835e26a5296?hl=en
336 148eb761aeaa4c3913e1766db0a7df0a5b5c8b20 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af Sebastian Thiel <byronimo@gmail.com> 1288198995 +0200 checkout: moving from master to 0.2.0-beta1
337 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af 148eb761aeaa4c3913e1766db0a7df0a5b5c8b20 Sebastian Thiel <byronimo@gmail.com> 1288199017 +0200 checkout: moving from 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af to master
338 148eb761aeaa4c3913e1766db0a7df0a5b5c8b20 8858a63cb33319f3e739edcbfafdae3ec0fefa33 Sebastian Thiel <byronimo@gmail.com> 1288199023 +0200 HEAD~1: updating HEAD
339 8858a63cb33319f3e739edcbfafdae3ec0fefa33 538e8265e04f69bb9bd73a10ddb4e8e9677fb140 Sebastian Thiel <byronimo@gmail.com> 1288199049 +0200 commit: docs: untracked_files is a property, but was used like a function, see http://groups.google.com/group/git-python/browse_thread/thread/84ed1835e26a5296?hl=en
340 538e8265e04f69bb9bd73a10ddb4e8e9677fb140 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af Sebastian Thiel <byronimo@gmail.com> 1288199066 +0200 checkout: moving from master to 0.2.0-beta1
341 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af ec97ed84d114ef131fa98acee4ce7be32f8c591f Sebastian Thiel <byronimo@gmail.com> 1288199163 +0200 commit: docs: untracked_files is a property, but was used like a function, see http://groups.google.com/group/git-python/browse_thread/thread/84ed1835e26a5296?hl=en
342 ec97ed84d114ef131fa98acee4ce7be32f8c591f ec97ed84d114ef131fa98acee4ce7be32f8c591f Sebastian Thiel <byronimo@gmail.com> 1288199260 +0200 checkout: moving from ec97ed84d114ef131fa98acee4ce7be32f8c591f to 0.2fixes
343 ec97ed84d114ef131fa98acee4ce7be32f8c591f 538e8265e04f69bb9bd73a10ddb4e8e9677fb140 Sebastian Thiel <byronimo@gmail.com> 1288199399 +0200 checkout: moving from 0.2 to master
344 538e8265e04f69bb9bd73a10ddb4e8e9677fb140 97ab197140b16027975c7465a5e8786e6cc8fea1 Sebastian Thiel <byronimo@gmail.com> 1288203452 +0200 commit (amend): docs: untracked_files is a property, but was used like a function, see http://groups.google.com/group/git-python/browse_thread/thread/84ed1835e26a5296?hl=en
345 97ab197140b16027975c7465a5e8786e6cc8fea1 3da3837fe2ec8152e1460f747d18290b52304868 Sebastian Thiel <byronimo@gmail.com> 1288203532 +0200 commit: cmd: improved error handling and debug printing
346 3da3837fe2ec8152e1460f747d18290b52304868 2c0b92e40ece170b59bced0cea752904823e06e7 Sebastian Thiel <byronimo@gmail.com> 1288203543 +0200 commit (amend): cmd: improved error handling and debug printing
347 2c0b92e40ece170b59bced0cea752904823e06e7 1b6b9510e0724bfcb4250f703ddf99d1e4020bbc Sebastian Thiel <byronimo@gmail.com> 1288205467 +0200 commit: Fixed bug that would cause the author's email to be a generic default one, instead of the existing and valid. The rest of the ConfigParser handling is correct, as it reads all configuration files available to git
348 1b6b9510e0724bfcb4250f703ddf99d1e4020bbc 0d5bfb5d6d22f8fe8c940f36e1fbe16738965d5f Sebastian Thiel <byronimo@gmail.com> 1288208986 +0200 commit: index.reset: updated parameter docs, but most importantly, the method now has better testing for the use of paths during reset. The IndexFile now implements this on its own, which also allows for something equivalent to git-reset --hard -- <paths>, which is not possible in the git command for some probably very good reason
349 0d5bfb5d6d22f8fe8c940f36e1fbe16738965d5f 702f3909520d39e8c343dece7b1e2d72e1479bbe Sebastian Thiel <byronimo@gmail.com> 1289032478 +0100 checkout: moving from master to integration
350 702f3909520d39e8c343dece7b1e2d72e1479bbe 0d5bfb5d6d22f8fe8c940f36e1fbe16738965d5f Sebastian Thiel <byronimo@gmail.com> 1289032798 +0100 checkout: moving from integration to master
351 0d5bfb5d6d22f8fe8c940f36e1fbe16738965d5f 735b28bc65964da5b181dffcccb1d05555b5acab Sebastian Thiel <byronimo@gmail.com> 1289033220 +0100 commit: test_refs: fixed failing tests just by making it less strict. It is dependent on the setup of the surrounding repository, hence the amount of ref-types found is actually variable, as long as they get more
352 735b28bc65964da5b181dffcccb1d05555b5acab 702f3909520d39e8c343dece7b1e2d72e1479bbe Sebastian Thiel <byronimo@gmail.com> 1289033228 +0100 checkout: moving from master to integration
353 702f3909520d39e8c343dece7b1e2d72e1479bbe b14a52ae2f8d6e38f57c34f8be150541cf00dafa Sebastian Thiel <byronimo@gmail.com> 1289034355 +0100 commit: Some cleanup of Daniels contribution. Now it appears to be ready for a merge
354 b14a52ae2f8d6e38f57c34f8be150541cf00dafa 90d73cd6ffa6e848da59cb2a35dec74e0fabd00a Sebastian Thiel <byronimo@gmail.com> 1289034615 +0100 commit (amend): Some cleanup of Daniels contribution. Now it appears to be ready for a merge
355 90d73cd6ffa6e848da59cb2a35dec74e0fabd00a 7bfca5efce8988e6070e7284bd409d1a731a3fbc Sebastian Thiel <byronimo@gmail.com> 1289034647 +0100 checkout: moving from integration to 0.1
356 7bfca5efce8988e6070e7284bd409d1a731a3fbc 90d73cd6ffa6e848da59cb2a35dec74e0fabd00a Sebastian Thiel <byronimo@gmail.com> 1289034656 +0100 merge integration: Fast-forward
357 90d73cd6ffa6e848da59cb2a35dec74e0fabd00a 735b28bc65964da5b181dffcccb1d05555b5acab Sebastian Thiel <byronimo@gmail.com> 1289034706 +0100 checkout: moving from 0.1 to master
358 735b28bc65964da5b181dffcccb1d05555b5acab bd7fb976ab0607592875b5697dc76c117a18dc73 Sebastian Thiel <byronimo@gmail.com> 1289034759 +0100 commit (amend): test_refs: fixed failing tests just by making it less strict. It is dependent on the setup of the surrounding repository, hence the amount of ref-types found is actually variable, as long as they get more
359 bd7fb976ab0607592875b5697dc76c117a18dc73 258403da9c2a087b10082d26466528fce3de38d4 Sebastian Thiel <byronimo@gmail.com> 1289338336 +0100 checkout: moving from master to 0.3.0-beta2
360 258403da9c2a087b10082d26466528fce3de38d4 bd7fb976ab0607592875b5697dc76c117a18dc73 Sebastian Thiel <byronimo@gmail.com> 1289338796 +0100 checkout: moving from 258403da9c2a087b10082d26466528fce3de38d4 to master
361 bd7fb976ab0607592875b5697dc76c117a18dc73 a1d1d2cb421f16bd277d7c4ce88398ff0f5afb29 Sebastian Thiel <byronimo@gmail.com> 1289379557 +0100 commit: tutorial: Fixed incorrect initialization code for bare repo, thank you, Bryan Bishop
362 a1d1d2cb421f16bd277d7c4ce88398ff0f5afb29 a1d1d2cb421f16bd277d7c4ce88398ff0f5afb29 Sebastian Thiel <byronimo@gmail.com> 1289385325 +0100 checkout: moving from master to submodule
363 a1d1d2cb421f16bd277d7c4ce88398ff0f5afb29 a1e2f63e64875a29e8c01a7ae17f5744680167a5 Sebastian Thiel <byronimo@gmail.com> 1289817434 +0100 commit: submodule: Fleshed out interface, and a partial test which is not yet usable. It showed that the ConfigParser needs some work. If the root is set, it also needs to refer to the root_commit instead of to the root-tree, as it will have to decide whether it works on the working tree's version of the .gitmodules file or the one in the repository
364 a1e2f63e64875a29e8c01a7ae17f5744680167a5 4d36f8ff4d1274a8815e932285ad6dbd6b2888af Sebastian Thiel <byronimo@gmail.com> 1289819639 +0100 commit: Improved GitConfigurationParser to better deal with streams and the corresponding locks. Submodule class now operates on parent_commits, the configuration is either streamed from the repository or written directly into a blob ( or file ) dependending on whether we have a working tree checkout or not which matches our parent_commit
365 4d36f8ff4d1274a8815e932285ad6dbd6b2888af 00ce31ad308ff4c7ef874d2fa64374f47980c85c Sebastian Thiel <byronimo@gmail.com> 1289836392 +0100 commit: Objects: Constructor now manually checks and sets the input arguments to the local cache - previously a procedural approach was used, which was less code, but slower too. Especially in case of CommitObjects unrolling the loop manually makes a difference.
366 00ce31ad308ff4c7ef874d2fa64374f47980c85c f97653aa06cf84bcf160be3786b6fce49ef52961 Sebastian Thiel <byronimo@gmail.com> 1289842964 +0100 commit: Repo: added submodule query and iteration methods similar to the ones provided for Remotes, including test
367 f97653aa06cf84bcf160be3786b6fce49ef52961 624556eae1c292a1dc283d9dca1557e28abe8ee3 Sebastian Thiel <byronimo@gmail.com> 1289844233 +0100 commit: Optimized test-decorators, by completely removing with_bare_rw_repo, which was mainly copy-paste from with_rw_repo, what a shame
368 624556eae1c292a1dc283d9dca1557e28abe8ee3 ceee7d7e0d98db12067744ac3cd0ab3a49602457 Sebastian Thiel <byronimo@gmail.com> 1289855525 +0100 commit: Added partial implementation of update, but realized that using refs in general may be contradicting if a tag is given there, as well as a commit sha of the submodule. Hence it should really be only a branch
369 ceee7d7e0d98db12067744ac3cd0ab3a49602457 d923bce2a8964541cf804428ccf3953ebbbdcf7d Sebastian Thiel <byronimo@gmail.com> 1289863093 +0100 commit: Submodule now only supports branches to be given as hint that will svn-external like behaviour. Implemented first version of update, which works for now, but probably needs to see more features
370 d923bce2a8964541cf804428ccf3953ebbbdcf7d d4fd7fca515ba9b088a7c811292f76f47d16cd7b Sebastian Thiel <byronimo@gmail.com> 1289863587 +0100 commit (amend): Submodule now only supports branches to be given as hint that will svn-external like behaviour. Implemented first version of update, which works for now, but probably needs to see more features
371 d4fd7fca515ba9b088a7c811292f76f47d16cd7b af5abca21b56fcf641ff916bd567680888c364aa Sebastian Thiel <byronimo@gmail.com> 1289896210 +0100 commit: Added a few utility methods and improved the test. Refs need an improvement though to allow easy configuration of branch-specific settings
372 af5abca21b56fcf641ff916bd567680888c364aa 38b81ad137e5f5486ce97a35702c84b9f869ccef Sebastian Thiel <byronimo@gmail.com> 1289901931 +0100 commit: remote: added methods to set and query the tracking branch status of normal heads, including test.
373 38b81ad137e5f5486ce97a35702c84b9f869ccef 9f73e8ba55f33394161b403bf7b8c2e0e05f47b0 Sebastian Thiel <byronimo@gmail.com> 1289901972 +0100 commit (amend): remote: added methods to set and query the tracking branch status of normal heads, including test.
374 9f73e8ba55f33394161b403bf7b8c2e0e05f47b0 3035781875f3004734ff5fe3be77f66b3cef299e Sebastian Thiel <byronimo@gmail.com> 1289903243 +0100 commit: Improved efficiency of the submodule.update process, improved test
375 3035781875f3004734ff5fe3be77f66b3cef299e 21b4db556619db2ef25f0e0d90fef7e38e6713e5 Sebastian Thiel <byronimo@gmail.com> 1289903575 +0100 commit (amend): Improved efficiency of the submodule.update process, improved test
376 21b4db556619db2ef25f0e0d90fef7e38e6713e5 78d2cd65b8b778f3b0cfef5268b0684314ca22ef Sebastian Thiel <byronimo@gmail.com> 1289905889 +0100 commit: implemented update to_last_revision option including test. Its now possible to update submodules such as svn-externals
377 78d2cd65b8b778f3b0cfef5268b0684314ca22ef c750f599a1b05ac855b55abc771729a704119833 Sebastian Thiel <byronimo@gmail.com> 1289924204 +0100 commit: Implemented deletion of submodules including proper tests
378 c750f599a1b05ac855b55abc771729a704119833 3d061a1a506b71234f783628ba54a7bdf79bbce9 Sebastian Thiel <byronimo@gmail.com> 1289924802 +0100 commit (amend): Implemented deletion of submodules including proper tests
379 3d061a1a506b71234f783628ba54a7bdf79bbce9 98e6edb546116cd98abdc3b37c6744e859bbde5c Sebastian Thiel <byronimo@gmail.com> 1289930487 +0100 commit: Initial implementation of submodule.add without any tests. These are to come next
380 98e6edb546116cd98abdc3b37c6744e859bbde5c 33964afb47ce3af8a32e6613b0834e5f94bdfe68 Sebastian Thiel <byronimo@gmail.com> 1289938053 +0100 commit: Added tests for all failure modes of submodule add ( except for one ), and fixed a few issues on the way
381 33964afb47ce3af8a32e6613b0834e5f94bdfe68 7b3ef45167e1c2f7d1b7507c13fcedd914f87da9 Sebastian Thiel <byronimo@gmail.com> 1289938869 +0100 commit: The submodule's branch is now a branch instance, not a plain string anymore
382 7b3ef45167e1c2f7d1b7507c13fcedd914f87da9 ef48ca5f54fe31536920ec4171596ff8468db5fe Sebastian Thiel <byronimo@gmail.com> 1289950137 +0100 commit: Added rest of submodule.add test code which should be pretty much 100% coverage for it
383 ef48ca5f54fe31536920ec4171596ff8468db5fe e84d05f4bbf7090a9802e9cd198d1c383974cb12 Sebastian Thiel <byronimo@gmail.com> 1289989025 +0100 commit: Repo: scetched out submodule_update
384 e84d05f4bbf7090a9802e9cd198d1c383974cb12 403c31fe3c7075652c892ecd3b6dc6d321bb1226 Sebastian Thiel <byronimo@gmail.com> 1290001921 +0100 commit: index: Sped up reading and writing of the index file by reducing the amount of attribute lookups considerably
385 403c31fe3c7075652c892ecd3b6dc6d321bb1226 b03933057df80ea9f860cc616eb7733f140f866e Sebastian Thiel <byronimo@gmail.com> 1290001937 +0100 commit (amend): index: Sped up reading and writing of the index file by reducing the amount of attribute lookups considerably
386 b03933057df80ea9f860cc616eb7733f140f866e a1e6234c27abf041e4c8cd1a799950e7cd9104f6 Sebastian Thiel <byronimo@gmail.com> 1290003888 +0100 commit: Inital implementation of Submodule.move including a very simple and to-be-improved test
387 a1e6234c27abf041e4c8cd1a799950e7cd9104f6 abda960de327e922fd9eaa429bef9e92918c8387 Sebastian Thiel <byronimo@gmail.com> 1290010524 +0100 commit: submodule: removed module_path method as it is implemented in the abspath property alrdeady
388 abda960de327e922fd9eaa429bef9e92918c8387 609a46a72764dc71104aa5d7b1ca5f53d4237a75 Sebastian Thiel <byronimo@gmail.com> 1290011090 +0100 commit (amend): submodule: removed module_path method as it is implemented in the abspath property alrdeady
389 609a46a72764dc71104aa5d7b1ca5f53d4237a75 6066f04d529b04e96295b37b5cceb2556414a472 Sebastian Thiel <byronimo@gmail.com> 1290025995 +0100 commit: repo: Added create_submodule method which fits into the tradition of offering a create_* method for most important entities.
390 6066f04d529b04e96295b37b5cceb2556414a472 609a46a72764dc71104aa5d7b1ca5f53d4237a75 Sebastian Thiel <byronimo@gmail.com> 1290026006 +0100 HEAD~1: updating HEAD
391 609a46a72764dc71104aa5d7b1ca5f53d4237a75 7cc4d748a132377ffe63534e9777d7541a3253c5 Sebastian Thiel <byronimo@gmail.com> 1290026013 +0100 commit: repo: Added create_submodule method which fits into the tradition of offering a create_* method for most important entities.
392 7cc4d748a132377ffe63534e9777d7541a3253c5 1687283c13caf7ff8d1959591541dff6a171ca1e Sebastian Thiel <byronimo@gmail.com> 1290029890 +0100 commit: RootModule.update: initial implementation of update method, which should be able to handle submodule removals, additions, path changes and branch changes. All this still needs to be tested though
393 1687283c13caf7ff8d1959591541dff6a171ca1e 9a0c4009edb35bb81d7e41d7d235675ccdfcffba Sebastian Thiel <byronimo@gmail.com> 1290068415 +0100 commit: commit: when creating a new commit and advancing the head, it will now write the ORIG_HEAD reference as well
394 9a0c4009edb35bb81d7e41d7d235675ccdfcffba 7a320abc52307b4d4010166bd899ac75024ec9a7 Sebastian Thiel <byronimo@gmail.com> 1290068612 +0100 commit (amend): commit: when creating a new commit and advancing the head, it will now write the ORIG_HEAD reference as well
395 7a320abc52307b4d4010166bd899ac75024ec9a7 1185ee2c9cda379bada7e08694f13dc124b27e93 Sebastian Thiel <byronimo@gmail.com> 1290073216 +0100 commit: ORIG_HEAD handling is now implemented in the ref-class itself, instead of being a special case of the commit method; includes tests
396 1185ee2c9cda379bada7e08694f13dc124b27e93 82849578e61a7dfb47fc76dcbe18b1e3b6a36951 Sebastian Thiel <byronimo@gmail.com> 1290073599 +0100 commit (amend): ORIG_HEAD handling is now implemented in the ref-class itself, instead of being a special case of the commit method; includes tests
397 82849578e61a7dfb47fc76dcbe18b1e3b6a36951 0c1834134ce177cdbd30a56994fcc4bf8f5be8b2 Sebastian Thiel <byronimo@gmail.com> 1290076876 +0100 commit: Added test-setup which can test all aspects of the (smart) update method
398 0c1834134ce177cdbd30a56994fcc4bf8f5be8b2 50095005bab7ffae14cb7d2ec8faeee7eed579ee Sebastian Thiel <byronimo@gmail.com> 1290096572 +0100 commit: first update test succeeds, so it verifies that existing repositories can be moved later if the configuration changed
399 50095005bab7ffae14cb7d2ec8faeee7eed579ee ca86a09651674d4bd2c22fd7f2f2ae6ca1c1d3d6 Sebastian Thiel <byronimo@gmail.com> 1290097988 +0100 commit (amend): first update test succeeds, so it verifies that existing repositories can be moved later if the configuration changed
400 ca86a09651674d4bd2c22fd7f2f2ae6ca1c1d3d6 bf2f7449beafcfb4578d08c90370d3953ff5f073 Sebastian Thiel <byronimo@gmail.com> 1290098006 +0100 commit (amend): first update test succeeds, so it verifies that existing repositories can be moved later if the configuration changed, and actually it also verifies that the url-change is handled correctly (as we changed the url from the default to the local path)
401 bf2f7449beafcfb4578d08c90370d3953ff5f073 c0990b2a6dd2e777b46c1685ddb985b3c0ef59a2 Sebastian Thiel <byronimo@gmail.com> 1290098151 +0100 commit (amend): first update test succeeds, so it verifies that existing repositories can be moved later if the configuration changed, and actually it also verifies that the url-change is handled correctly (as we changed the url from the default to the local path)
402 c0990b2a6dd2e777b46c1685ddb985b3c0ef59a2 cf5eaddde33e983bc7b496f458bdd49154f6f498 Sebastian Thiel <byronimo@gmail.com> 1290109461 +0100 commit: Updated tests and implementation to verify functionality for handling submodule removals, as well as url changes
403 cf5eaddde33e983bc7b496f458bdd49154f6f498 3f2d76ba8e6d004ff5849ed8c7c34f6a4ac2e1e3 Sebastian Thiel <byronimo@gmail.com> 1290112561 +0100 commit: Added test for branch changes - it appears to work well, at least as far as the restricted tests are concerned
404 3f2d76ba8e6d004ff5849ed8c7c34f6a4ac2e1e3 ebe8f644e751c1b2115301c1a961bef14d2cce89 Sebastian Thiel <byronimo@gmail.com> 1290114666 +0100 commit: Added test for the recursive code path.
405 ebe8f644e751c1b2115301c1a961bef14d2cce89 ebe8f644e751c1b2115301c1a961bef14d2cce89 Sebastian Thiel <byronimo@gmail.com> 1290114835 +0100 checkout: moving from submodule to refactor
406 ebe8f644e751c1b2115301c1a961bef14d2cce89 4c34d5c3f2a4ed7194276a026e0ec6437d339c67 Sebastian Thiel <byronimo@gmail.com> 1290116693 +0100 commit: Split big submodule file into smaller files. Tried to manually get imports right, but its not yet tested
407 4c34d5c3f2a4ed7194276a026e0ec6437d339c67 9519f186ce757cdba217f222c95c20033d00f91d Sebastian Thiel <byronimo@gmail.com> 1290118223 +0100 commit: Fixed all imports, refactoring appears to be complete
408 9519f186ce757cdba217f222c95c20033d00f91d ebe8f644e751c1b2115301c1a961bef14d2cce89 Sebastian Thiel <byronimo@gmail.com> 1290118281 +0100 checkout: moving from refactor to submodule
409 ebe8f644e751c1b2115301c1a961bef14d2cce89 7cf2d5fcf0a3db793678dd6ba9fc1c24d4eeb36a Sebastian Thiel <byronimo@gmail.com> 1290118286 +0100 merge refactor: Merge made by recursive.
410 7cf2d5fcf0a3db793678dd6ba9fc1c24d4eeb36a a1d1d2cb421f16bd277d7c4ce88398ff0f5afb29 Sebastian Thiel <byronimo@gmail.com> 1290118288 +0100 checkout: moving from submodule to master
411 a1d1d2cb421f16bd277d7c4ce88398ff0f5afb29 f1545bd9cd6953c5b39c488bf7fe179676060499 Sebastian Thiel <byronimo@gmail.com> 1290118292 +0100 merge submodule: Merge made by recursive.
412 f1545bd9cd6953c5b39c488bf7fe179676060499 f1545bd9cd6953c5b39c488bf7fe179676060499 Sebastian Thiel <byronimo@gmail.com> 1290119272 +0100 checkout: moving from master to docs
413 f1545bd9cd6953c5b39c488bf7fe179676060499 75c75fa136f6181f6ba2e52b8b85a98d3fe1718e Sebastian Thiel <byronimo@gmail.com> 1290120222 +0100 commit: Changed name/id of gitdb submodule to something that doesn't look like a path
414 75c75fa136f6181f6ba2e52b8b85a98d3fe1718e a25e1d4aa7e5898ab1224d0e5cc5ecfbe8ed8821 Sebastian Thiel <byronimo@gmail.com> 1290122817 +0100 commit: Updated tutorial with a brief introduction to submodules
415 a25e1d4aa7e5898ab1224d0e5cc5ecfbe8ed8821 a8014d2ec56fd684dc81478dee73ca7eda0ab8a7 Sebastian Thiel <byronimo@gmail.com> 1290122851 +0100 commit: Updated gitdb submodule, and added note about how the submodule package manages its dependencies
416 a8014d2ec56fd684dc81478dee73ca7eda0ab8a7 f1545bd9cd6953c5b39c488bf7fe179676060499 Sebastian Thiel <byronimo@gmail.com> 1290122855 +0100 checkout: moving from docs to master
417 f1545bd9cd6953c5b39c488bf7fe179676060499 45c0f285a6d9d9214f8167742d12af2855f527fb Sebastian Thiel <byronimo@gmail.com> 1290122860 +0100 merge docs: Merge made by recursive.
418 45c0f285a6d9d9214f8167742d12af2855f527fb 315c303214cef855499f0c7eda46b7ed82dceecb Sebastian Thiel <byronimo@gmail.com> 1290158850 +0100 commit: test_submodule: fixed failures that arose due to changes of the original submodule names. Also, a major bug was fixed that cased submodules to always being updated recursively when using the RootModule.update method
419 315c303214cef855499f0c7eda46b7ed82dceecb 7dd618655c96ff32b5c30e41a5406c512bcbb65f Sebastian Thiel <byronimo@gmail.com> 1290158895 +0100 commit (amend): test_submodule: fixed failures that arose due to changes of the original submodule names. Also, a major bug was fixed that cased submodules to always being updated recursively when using the RootModule.update method
420 7dd618655c96ff32b5c30e41a5406c512bcbb65f 2ab454f0ccf09773a4f51045329a69fd73559414 Sebastian Thiel <byronimo@gmail.com> 1290188727 +0100 commit: remote: parsing of fetch information now reacts to fatal errors. Previously it would just bump into an assertion
421 2ab454f0ccf09773a4f51045329a69fd73559414 b00ad00130389f5b00da9dbfd89c3e02319d2999 Sebastian Thiel <byronimo@gmail.com> 1290196658 +0100 commit: submodule: When adding an existing submodule, when retrieving the binsha, we will now consider not only the tree, but the index too
422 b00ad00130389f5b00da9dbfd89c3e02319d2999 8867348ca772cdce7434e76eed141f035b63e928 Sebastian Thiel <byronimo@gmail.com> 1290196804 +0100 commit: Bumped version number to 0.3.1
423 8867348ca772cdce7434e76eed141f035b63e928 8d0aa1ef19e2c3babee458bd4504820f415148e0 Sebastian Thiel <byronimo@gmail.com> 1290271885 +0100 commit: Fixed performance tests which broke in the meanwhile - they definitely don't run often enough, which is because they intentionally don't have a package initialization file
424 8d0aa1ef19e2c3babee458bd4504820f415148e0 8e0e315a371cdfc80993a1532f938d56ed7acee4 Sebastian Thiel <byronimo@gmail.com> 1290280591 +0100 commit: submodule: Fixed capital error when handling the submodule's branch, which was returned in the submodules super repository, not in the submodule's module
425 8e0e315a371cdfc80993a1532f938d56ed7acee4 7c72b9a3eaabbe927ba77d4f69a62f35fbe60e2e Sebastian Thiel <byronimo@gmail.com> 1290286993 +0100 merge gitorious/win32: Merge made by recursive.
426 7c72b9a3eaabbe927ba77d4f69a62f35fbe60e2e 7c72b9a3eaabbe927ba77d4f69a62f35fbe60e2e Sebastian Thiel <byronimo@gmail.com> 1290287857 +0100 checkout: moving from master to osx
427 7c72b9a3eaabbe927ba77d4f69a62f35fbe60e2e 6c6223b854e4c7985b08493a027b47f668493832 Sebastian Thiel <byronimo@gmail.com> 1290287908 +0100 commit: testing:added special case for osx to solve a special issue with the temp directory
428 6c6223b854e4c7985b08493a027b47f668493832 20b07fa542d2376a287435a26c967a5ee104667f Sebastian Thiel <byronimo@gmail.com> 1290288287 +0100 commit (amend): testing:added special case for osx to solve a special issue with the temp directory
429 20b07fa542d2376a287435a26c967a5ee104667f 7c72b9a3eaabbe927ba77d4f69a62f35fbe60e2e Sebastian Thiel <byronimo@gmail.com> 1290288327 +0100 checkout: moving from osx to master
430 7c72b9a3eaabbe927ba77d4f69a62f35fbe60e2e 517ae56f517f5e7253f878dd1dc3c7c49f53df1a Sebastian Thiel <byronimo@gmail.com> 1290288333 +0100 merge osx: Merge made by recursive.
431 517ae56f517f5e7253f878dd1dc3c7c49f53df1a 22a88a7ec38e29827264f558f0c1691b99102e23 Sebastian Thiel <byronimo@gmail.com> 1290289085 +0100 commit: fixed performance tests ... again, previously I was just working on an incorrect repository
432 22a88a7ec38e29827264f558f0c1691b99102e23 685760ab33b8f9d7455b18a9ecb8c4c5b3315d66 Sebastian Thiel <byronimo@gmail.com> 1290342054 +0100 commit: Added zip_safe info to setup.py file
433 685760ab33b8f9d7455b18a9ecb8c4c5b3315d66 9d6310db456de9952453361c860c3ae61b8674ea Sebastian Thiel <byronimo@gmail.com> 1290342681 +0100 commit: docs: added final docs for version 0.3.0, started new release 0.3.1
434 9d6310db456de9952453361c860c3ae61b8674ea 0b813371f5a8af95152cae109d28c7c97bfaf79f Sebastian Thiel <byronimo@gmail.com> 1290358083 +0100 commit: Fixed API reference docs as far as possible
435 0b813371f5a8af95152cae109d28c7c97bfaf79f 0b813371f5a8af95152cae109d28c7c97bfaf79f Sebastian Thiel <byronimo@gmail.com> 1290363019 +0100 checkout: moving from master to structure
436 0b813371f5a8af95152cae109d28c7c97bfaf79f fafe8a77db75083de3e7af92185ecdb7f2d542d3 Sebastian Thiel <byronimo@gmail.com> 1290363468 +0100 commit: moved all contents, incl. submodule gitdb, up to the root directory
437 fafe8a77db75083de3e7af92185ecdb7f2d542d3 e6019e16d5a74dc49eb7129ee7fd78b4de51dac2 Sebastian Thiel <byronimo@gmail.com> 1290363544 +0100 commit: flattened test folder structure, didn't adjust any file content yet
438 e6019e16d5a74dc49eb7129ee7fd78b4de51dac2 83a9e4a0dad595188ff3fb35bc3dfc4d931eff6d Sebastian Thiel <byronimo@gmail.com> 1290366107 +0100 commit: Fixed setup script to work with changed folder structure
439 83a9e4a0dad595188ff3fb35bc3dfc4d931eff6d 557800a1eba3b9cface0f319d8e6aa6bd2ec188d Sebastian Thiel <byronimo@gmail.com> 1290367011 +0100 commit: Updated MANIFEST and setup to include fixtures. Adjusted includes in all tests to work with the new directory structure
440 557800a1eba3b9cface0f319d8e6aa6bd2ec188d 9ca0f897376e765989e92e44628228514f431458 Sebastian Thiel <byronimo@gmail.com> 1290371673 +0100 commit (amend): Updated MANIFEST and setup to include fixtures. Adjusted includes in all tests to work with the new directory structure
441 9ca0f897376e765989e92e44628228514f431458 0b813371f5a8af95152cae109d28c7c97bfaf79f Sebastian Thiel <byronimo@gmail.com> 1290372294 +0100 checkout: moving from structure to master
442 0b813371f5a8af95152cae109d28c7c97bfaf79f 9ca0f897376e765989e92e44628228514f431458 Sebastian Thiel <byronimo@gmail.com> 1290372302 +0100 checkout: moving from master to structure
443 9ca0f897376e765989e92e44628228514f431458 6befb28efd86556e45bb0b213bcfbfa866cac379 Sebastian Thiel <byronimo@gmail.com> 1290372430 +0100 commit: updated changelog
444 6befb28efd86556e45bb0b213bcfbfa866cac379 0b813371f5a8af95152cae109d28c7c97bfaf79f Sebastian Thiel <byronimo@gmail.com> 1290372432 +0100 checkout: moving from structure to master
445 0b813371f5a8af95152cae109d28c7c97bfaf79f 94140bbfc523ae13e1e8045ebfed8a76fe0a1872 Sebastian Thiel <byronimo@gmail.com> 1290372438 +0100 merge structure: Merge made by recursive.
446 94140bbfc523ae13e1e8045ebfed8a76fe0a1872 d01b428dbac4103b4f7d7b8fca32e01f70746c53 Sebastian Thiel <byronimo@gmail.com> 1290372442 +0100 commit (amend): !!WARNING!!: Directory structure changed, see commit message for instructions
447 d01b428dbac4103b4f7d7b8fca32e01f70746c53 db3423d1eab11d00c5475e36eae8952512b07f4e Sebastian Thiel <byronimo@gmail.com> 1290373147 +0100 commit (amend): !**WARNING**!: Directory structure changed, see commit message for instructions
448 db3423d1eab11d00c5475e36eae8952512b07f4e 5ed5b2011ec7cf72f19e6d53b588eea4adca68e5 Sebastian Thiel <byronimo@gmail.com> 1290373168 +0100 commit (amend): *!*WARNING*!*: Directory structure changed, see commit message for instructions
449 5ed5b2011ec7cf72f19e6d53b588eea4adca68e5 470d4a7cc865d2702c326d9d1d1b0ab7afb49f0e Sebastian Thiel <byronimo@gmail.com> 1290373186 +0100 commit (amend): !##WARNING##!: Directory structure changed, see commit message for instructions
450 470d4a7cc865d2702c326d9d1d1b0ab7afb49f0e e088424eb01bd47c6f0d313f465a21ee742e6f4a Sebastian Thiel <byronimo@gmail.com> 1290373209 +0100 commit (amend): If you use git-python as a submodule of your own project, which alters the sys.path to import it,
451 e088424eb01bd47c6f0d313f465a21ee742e6f4a 48a17c87c15b2fa7ce2e84afa09484f354d57a39 Sebastian Thiel <byronimo@gmail.com> 1290373245 +0100 commit (amend): -#######->WARNING<-####### Directory structure changed, see commit message
452 48a17c87c15b2fa7ce2e84afa09484f354d57a39 fca367548e365f93c58c47dea45507025269f59a Sebastian Thiel <byronimo@gmail.com> 1290374761 +0100 commit: Changed version to 0.3.1 (removed beta1) so that other projects can actually depend on git-python using the setuptools. Previously it would claim the version did not exist, probably because the setuptools are just comparing strings
453 fca367548e365f93c58c47dea45507025269f59a fca367548e365f93c58c47dea45507025269f59a Sebastian Thiel <byronimo@gmail.com> 1290435685 +0100 checkout: moving from master to refs
454 fca367548e365f93c58c47dea45507025269f59a dec4663129f72321a14efd6de63f14a7419e3ed2 Sebastian Thiel <byronimo@gmail.com> 1290500057 +0100 commit: Split ref implementation up into multiple files, to make room for the log implementation
455 dec4663129f72321a14efd6de63f14a7419e3ed2 fca367548e365f93c58c47dea45507025269f59a Sebastian Thiel <byronimo@gmail.com> 1290500094 +0100 checkout: moving from refs to master
456 fca367548e365f93c58c47dea45507025269f59a dec4663129f72321a14efd6de63f14a7419e3ed2 Sebastian Thiel <byronimo@gmail.com> 1290500104 +0100 checkout: moving from master to refs
457 dec4663129f72321a14efd6de63f14a7419e3ed2 739fa140235cc9d65c632eaf1f5cacc944d87cfb Sebastian Thiel <byronimo@gmail.com> 1290501284 +0100 commit: Fixed remaining tests - lets hope that everything is indeed working correctly - as imports changed, every line of code needs to be run to assure all names can be resolved
458 739fa140235cc9d65c632eaf1f5cacc944d87cfb d89b2cbcd57ecd5600ecf0202b396141c1a856a3 Sebastian Thiel <byronimo@gmail.com> 1290512134 +0100 commit: Initial interface including some of the implementation of the RefLog. TestCase scetched out for now
459 d89b2cbcd57ecd5600ecf0202b396141c1a856a3 6e5aae2fc8c3832bdae1cd5e0a269405fb059231 Sebastian Thiel <byronimo@gmail.com> 1290512159 +0100 commit (amend): Initial interface including some of the implementation of the RefLog. TestCase scetched out for now
+0
-2
git/test/fixtures/reflog_invalid_date less more
0 501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <byronimo@gmail.com> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
1 82b8902e033430000481eb355733cd7065342037 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <byronimo@gmail.com> 1271229940 commit: conf.py: Adjusted version to match with the actual version
+0
-2
git/test/fixtures/reflog_invalid_email less more
0 501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <byronimo@gmail.com> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
1 82b8902e033430000481eb355733cd7065342037 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <byronimo@gmail. 1271229940 +0200 commit: conf.py: Adjusted version to match with the actual version
+0
-2
git/test/fixtures/reflog_invalid_newsha less more
0 501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <byronimo@gmail.com> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
1 82b8902e033430000481eb355733cd7065342037 69361d96a59381fde0ac34d19df2d Sebastian Thiel <byronimo@gmail.com> 1271229940 +0200 commit: conf.py: Adjusted version to match with the actual version
+0
-2
git/test/fixtures/reflog_invalid_oldsha less more
0 501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <byronimo@gmail.com> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
1 82b8902e033430000481eb3 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <byronimo@gmail.com> 1271229940 +0200 commit: conf.py: Adjusted version to match with the actual version
+0
-2
git/test/fixtures/reflog_invalid_sep less more
0 501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <byronimo@gmail.com> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
1 82b8902e033430000481eb355733cd7065342037 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <byronimo@gmail.com> 1271229940 +0200 commit: conf.py: Adjusted version to match with the actual version
+0
-124
git/test/fixtures/reflog_master less more
0 501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <byronimo@gmail.com> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
1 82b8902e033430000481eb355733cd7065342037 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <byronimo@gmail.com> 1271229940 +0200 commit: conf.py: Adjusted version to match with the actual version
2 69361d96a59381fde0ac34d19df2d4aff05fb9a9 0d6ceabf5b90e7c0690360fc30774d36644f563c Sebastian Thiel <byronimo@gmail.com> 1272614247 +0200 merge integration: Fast-forward
3 22a0289972b365b7912340501b52ca3dd98be289 143b927307d46ccb8f1cc095739e9625c03c82ff Sebastian Thiel <byronimo@gmail.com> 1272988814 +0200 commit: TODO: Removed all entries but left a mesage about where to find the issuee on lighthouse.
4 143b927307d46ccb8f1cc095739e9625c03c82ff e41c727be8dbf8f663e67624b109d9f8b135a4ab Sebastian Thiel <byronimo@gmail.com> 1273140152 +0200 commit: README: Added mailing list and issue tracker information
5 c083f3d0b853e723d0d4b00ff2f1ec5f65f05cba de5bc8f7076c5736ef1efa57345564fbc563bd19 Sebastian Thiel <byronimo@gmail.com> 1273522570 +0200 commit: Handle filenames with embedded spaces when generating diffs
6 de5bc8f7076c5736ef1efa57345564fbc563bd19 8caeec1b15645fa53ec5ddc6e990e7030ffb7c5a Sebastian Thiel <byronimo@gmail.com> 1273529174 +0200 commit: IndexFile.add: Fixed incorrect path handling if path rewriting was desired and absolute paths were given
7 600fcbc1a2d723f8d51e5f5ab6d9e4c389010e1c 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af Sebastian Thiel <byronimo@gmail.com> 1274811103 +0200 commit: diff: by limiting the splitcount to 5, a subtle bug was introduced as the newline at the end of the split line was not split away automatically. Added test for this, and the trivial fix
8 1019d4cf68d1acdbb4d6c1abb7e71ac9c0f581af 17af1f64d5f1e62d40e11b75b1dd48e843748b49 Sebastian Thiel <byronimo@gmail.com> 1274877948 +0200 commit: BlockingLockFile: added sanity check that raises IOError if the directory containing the lock was removed. This is unlikely to happen in a production envrironment, but may happen during testing, as folders are moved/deleted once the test is complete. Daemons might still be waiting for something, and they should be allowed to terminate instead of waiting for a possibly long time
9 17af1f64d5f1e62d40e11b75b1dd48e843748b49 34ba8ffba0b3b4d21da7bcea594cc3631e422142 Sebastian Thiel <byronimo@gmail.com> 1274906080 +0200 commit: refs: a Reference can now be created by assigning a commit or object (for convenience)
10 34ba8ffba0b3b4d21da7bcea594cc3631e422142 11dc82538cc1ebb537c866c8e76146e384cdfe24 Sebastian Thiel <byronimo@gmail.com> 1274906333 +0200 commit: refs: a Reference can now be created by assigning a commit or object (for convenience)
11 11dc82538cc1ebb537c866c8e76146e384cdfe24 34ba8ffba0b3b4d21da7bcea594cc3631e422142 Sebastian Thiel <byronimo@gmail.com> 1274906338 +0200 HEAD~1: updating HEAD
12 34ba8ffba0b3b4d21da7bcea594cc3631e422142 de84cbdd0f9ef97fcd3477b31b040c57192e28d9 Sebastian Thiel <byronimo@gmail.com> 1274906431 +0200 commit (amend): refs: a Reference can now be created by assigning a commit or object (for convenience)
13 de84cbdd0f9ef97fcd3477b31b040c57192e28d9 ecf37a1b4c2f70f1fc62a6852f40178bf08b9859 Sebastian Thiel <byronimo@gmail.com> 1274910053 +0200 commit: index: index-add fixed to always append a newline after each item. In git has unified its way it reads from stdin, now it wants all items to be terminated by a newline usually. Previously, it could have been that it really didn't want to have a termination character when the last item was written to the file. Bumped the minimum requirements to 1.7.0 to be sure it is working as I think it will.
14 ecf37a1b4c2f70f1fc62a6852f40178bf08b9859 1ee2afb00afaf77c883501eac8cd614c8229a444 Sebastian Thiel <byronimo@gmail.com> 1274914700 +0200 commit: cmd: By default, on linux, the parent file handles will be closed to leave the child less cluttered, and make it easier to debug as it will only have the file descriptors we set. It appears to be more stable regarding the stdin-is-closed-but-child-doesn't-realize-this issue
15 1ee2afb00afaf77c883501eac8cd614c8229a444 bd45e9267ab0d3f37e59ecc8b87d0ad19abad4ad Sebastian Thiel <byronimo@gmail.com> 1275324366 +0200 commit: gitcmd: may now receive extra keyword arguments to be passed directly to the subproces.Popen invocation. It could be used to pass custom environments, without changing the own one
16 bd45e9267ab0d3f37e59ecc8b87d0ad19abad4ad 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e Sebastian Thiel <byronimo@gmail.com> 1275324409 +0200 commit (amend): gitcmd: may now receive extra keyword arguments to be passed directly to the subproces.Popen invocation. It could be used to pass custom environments, without changing the own one (#26)
17 6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e e79999c956e2260c37449139080d351db4aa3627 Sebastian Thiel <byronimo@gmail.com> 1275549608 +0200 commit: git.cmd: moved hardcoded chunksize when duplicating stream data into easy-to-change class member variable
18 e79999c956e2260c37449139080d351db4aa3627 412632599479a8e5991a07ecb67bc52b85c60755 Sebastian Thiel <byronimo@gmail.com> 1275550524 +0200 commit: git.cmd: using communicate in the main branch of execution, which might not make a big difference, but perhaps its smarter about broken pipes.
19 412632599479a8e5991a07ecb67bc52b85c60755 25dca42bac17d511b7e2ebdd9d1d679e7626db5f Sebastian Thiel <byronimo@gmail.com> 1275550670 +0200 commit (amend): git.cmd: using communicate in the main branch of execution, which might not make a big difference, but perhaps its smarter about broken pipes.
20 25dca42bac17d511b7e2ebdd9d1d679e7626db5f 6fbb69306c0e14bacb8dcb92a89af27d3d5d631f Sebastian Thiel <byronimo@gmail.com> 1275665431 +0200 commit (merge): Merge branch 'odb'
21 6fbb69306c0e14bacb8dcb92a89af27d3d5d631f a243827ab3346e188e99db2f9fc1f916941c9b1a Sebastian Thiel <byronimo@gmail.com> 1275685591 +0200 commit: Implemented stream tests, found a bug on the way, slowly a test-framework for streams starts to show up, but its not yet there
22 a243827ab3346e188e99db2f9fc1f916941c9b1a 7c1169f6ea406fec1e26e99821e18e66437e65eb Sebastian Thiel <byronimo@gmail.com> 1275690001 +0200 commit: Removed compression flag from IStream and OStream types, as a valid object will always be compressed if generated by the system ( even future memory db's will compress it )
23 7c1169f6ea406fec1e26e99821e18e66437e65eb c69b6b979e3d6bd01ec40e75b92b21f7a391f0ca Sebastian Thiel <byronimo@gmail.com> 1275746174 +0200 commit: Added basic channel implementation including test
24 c69b6b979e3d6bd01ec40e75b92b21f7a391f0ca 7c1169f6ea406fec1e26e99821e18e66437e65eb Sebastian Thiel <byronimo@gmail.com> 1275746196 +0200 HEAD~1: updating HEAD
25 7c1169f6ea406fec1e26e99821e18e66437e65eb f91495e271597034226f1b9651345091083172c4 Sebastian Thiel <byronimo@gmail.com> 1276339280 +0200 merge async: Merge made by recursive.
26 f91495e271597034226f1b9651345091083172c4 5c631ca192848fed3068b31b1389cd92a0c0cdca Sebastian Thiel <byronimo@gmail.com> 1276340638 +0200 commit: Removed async from this repository, put it into own one which now comes in as external, using a git-submodule
27 5c631ca192848fed3068b31b1389cd92a0c0cdca f91495e271597034226f1b9651345091083172c4 Sebastian Thiel <byronimo@gmail.com> 1276345979 +0200 HEAD~1: updating HEAD
28 f91495e271597034226f1b9651345091083172c4 86ea63504f3e8a74cfb1d533be9d9602d2d17e27 Sebastian Thiel <byronimo@gmail.com> 1276346049 +0200 commit: Removed async from tree
29 86ea63504f3e8a74cfb1d533be9d9602d2d17e27 6c1faef799095f3990e9970bc2cb10aa0221cf9c Sebastian Thiel <byronimo@gmail.com> 1276356043 +0200 commit: Removed odb from project, it is now used as a submodule named gitdb, which was added instead
30 6c1faef799095f3990e9970bc2cb10aa0221cf9c 28ed48c93f4cc8b6dd23c951363e5bd4e6880992 Sebastian Thiel <byronimo@gmail.com> 1276503381 +0200 commit: Implemented initial version of tree serialization which appears to work according to a simple test
31 28ed48c93f4cc8b6dd23c951363e5bd4e6880992 fe5289ed8311fecf39913ce3ae86b1011eafe5f7 Sebastian Thiel <byronimo@gmail.com> 1276506168 +0200 commit: tree now uses less memory for its cache as it stores the bare deserialized information - this also speeds up later serialization after changes. its clear though that retrieving actual objects is slower currently as these are not cached anymore. Its worth thinking about moving these encoding, decoding routines to gitdb
32 fe5289ed8311fecf39913ce3ae86b1011eafe5f7 f8dabbf4f92a7023181777e9d40355562474f71a Sebastian Thiel <byronimo@gmail.com> 1276512508 +0200 commit: tree: added TreeModifier, allowing to adjust existing trees safely and or fast, while staying compatible with serialization which requires it to be sorted
33 f8dabbf4f92a7023181777e9d40355562474f71a d9240918aa03e49feabe43af619019805ac76786 Sebastian Thiel <byronimo@gmail.com> 1276512707 +0200 commit (amend): tree: added TreeModifier, allowing to adjust existing trees safely and or fast, while staying compatible with serialization which requires it to be sorted
34 d9240918aa03e49feabe43af619019805ac76786 38b3cfb9b24a108e0720f7a3f8d6355f7e0bb1a9 Sebastian Thiel <byronimo@gmail.com> 1276527612 +0200 merge index: Merge made by recursive.
35 38b3cfb9b24a108e0720f7a3f8d6355f7e0bb1a9 c9dbf201b4f0b3c2b299464618cb4ecb624d272c Sebastian Thiel <byronimo@gmail.com> 1276529105 +0200 commit: Moved small types that had their own module into the utils module
36 c9dbf201b4f0b3c2b299464618cb4ecb624d272c 45e87305bd4f050c2d0309c32fe5de499fc38df3 Sebastian Thiel <byronimo@gmail.com> 1276554725 +0200 commit: Reimplemented Lock handling to be conforming to the git lock protocol, which is actually more efficient than the previous implementation
37 45e87305bd4f050c2d0309c32fe5de499fc38df3 06590aee389f4466e02407f39af1674366a74705 Sebastian Thiel <byronimo@gmail.com> 1276555536 +0200 commit (amend): Reimplemented Lock handling to be conforming to the git lock protocol, which is actually more efficient than the previous implementation
38 06590aee389f4466e02407f39af1674366a74705 1d2307532d679393ae067326e4b6fa1a2ba5cc06 Sebastian Thiel <byronimo@gmail.com> 1276556905 +0200 commit: Moved LockedFD and its test into the gitdb project
39 1d2307532d679393ae067326e4b6fa1a2ba5cc06 e837b901dcfac82e864f806c80f4a9cbfdb9c9f3 Sebastian Thiel <byronimo@gmail.com> 1276607908 +0200 commit: Move LazyMixin type to gitdb, index reading now uses file_contents_ro from gitdb as well
40 e837b901dcfac82e864f806c80f4a9cbfdb9c9f3 b82dbf538ac0d03968a0f5b7e2318891abefafaa Sebastian Thiel <byronimo@gmail.com> 1276870827 +0200 commit: GitCmd implementation of gitdb base moved to git-python where it belongs. Previously it was located in gitdb, which doesn't have any facilities to use the git command
41 b82dbf538ac0d03968a0f5b7e2318891abefafaa f164627a85ed7b816759871a76db258515b85678 Sebastian Thiel <byronimo@gmail.com> 1277057845 +0200 commit: db: added pure python git database
42 f164627a85ed7b816759871a76db258515b85678 ac62760c52abf28d1fd863f0c0dd48bc4a23d223 Sebastian Thiel <byronimo@gmail.com> 1277117506 +0200 commit: index.add: now uses gitdb.store functionality instead of git-hash-file. The python version is about as fast, but could support multithreading using async
43 ac62760c52abf28d1fd863f0c0dd48bc4a23d223 0fdf6c3aaff49494c47aaeb0caa04b3016e10a26 Sebastian Thiel <byronimo@gmail.com> 1277127929 +0200 commit: index: Entries are now using flags internally, instead of reducing the flag information to just the stage ( just to be closer to the git-original )
44 0fdf6c3aaff49494c47aaeb0caa04b3016e10a26 0aeb491d3d8f53e07fb21f36251be4880170c5ab Sebastian Thiel <byronimo@gmail.com> 1277129321 +0200 commit: index.add does not need the git clt anymore
45 0aeb491d3d8f53e07fb21f36251be4880170c5ab 91725f0fc59aa05ef68ab96e9b29009ce84668a5 Sebastian Thiel <byronimo@gmail.com> 1277129385 +0200 commit (amend): index.add does not need the git clt anymore
46 91725f0fc59aa05ef68ab96e9b29009ce84668a5 778234d544b3f58dd415aaf10679d15b01a5281f Sebastian Thiel <byronimo@gmail.com> 1277201033 +0200 merge writetree: Merge made by recursive.
47 778234d544b3f58dd415aaf10679d15b01a5281f 57050184f3d962bf91511271af59ee20f3686c3f Sebastian Thiel <byronimo@gmail.com> 1277301014 +0200 merge fromtree: Merge made by recursive.
48 57050184f3d962bf91511271af59ee20f3686c3f 129f90aa8d83d9b250c87b0ba790605c4a2bb06a Sebastian Thiel <byronimo@gmail.com> 1277334478 +0200 commit: Multiple partly critical bugfixes related to index handling
49 129f90aa8d83d9b250c87b0ba790605c4a2bb06a a1adb421c2ee3e4868ea70d440dd82896219ed8f Sebastian Thiel <byronimo@gmail.com> 1277388148 +0200 commit: aggressive_tree_merge: fixed incorrect handling of one branch, it was just not implemented causing incorrect merge results. Added test to cover this issue
50 a1adb421c2ee3e4868ea70d440dd82896219ed8f 55dcc17c331f580b3beeb4d5decf64d3baf94f2e Sebastian Thiel <byronimo@gmail.com> 1277395720 +0200 commit (amend): aggressive_tree_merge: fixed incorrect handling of one branch, it was just not implemented causing incorrect merge results. Added test to cover this issue
51 55dcc17c331f580b3beeb4d5decf64d3baf94f2e ca131dd61e26f46f49ee3f70763f994cf9512665 Sebastian Thiel <byronimo@gmail.com> 1277401303 +0200 commit: GitCmdStreamReader: fixed terrible bug which only kicked in if the stream was actually empty. This is a rare case that can happen during stream testing. Theoretically there shouldn't be any empty streams of course, but practically they do exist sometimes ;)
52 ca131dd61e26f46f49ee3f70763f994cf9512665 feb1ea0f4aacb9ea6dc4133900e65bf34c0ee02d Sebastian Thiel <byronimo@gmail.com> 1277401306 +0200 commit (amend): GitCmdStreamReader: fixed terrible bug which only kicked in if the stream was actually empty. This is a rare case that can happen during stream testing. Theoretically there shouldn't be any empty streams of course, but practically they do exist sometimes ;); fixed stream.seek implementation, which previously used seek on standard output
53 feb1ea0f4aacb9ea6dc4133900e65bf34c0ee02d 402a6c2808db4333217aa300d0312836fd7923bd Sebastian Thiel <byronimo@gmail.com> 1277407147 +0200 commit: IndexFile.add: writing of the index file can now optionally be turned off. The default is to write the physical index, which is the behaviour you would expect
54 402a6c2808db4333217aa300d0312836fd7923bd 58fb1187b7b8f1e62d3930bdba9be5aba47a52c6 Sebastian Thiel <byronimo@gmail.com> 1277473196 +0200 merge index: Fast-forward
55 58fb1187b7b8f1e62d3930bdba9be5aba47a52c6 8d2239f24f6a54d98201413d4f46256df0d6a5f3 Sebastian Thiel <byronimo@gmail.com> 1277745383 +0200 merge sha20: Merge made by recursive.
56 8d2239f24f6a54d98201413d4f46256df0d6a5f3 f1401803ccf7db5d897a5ef4b27e2176627c430e Sebastian Thiel <byronimo@gmail.com> 1277756712 +0200 commit: Fixed performance tests which broke in the course of the sha1-20 byte changes
57 f1401803ccf7db5d897a5ef4b27e2176627c430e 6917ae4ce9eaa0f5ea91592988c1ea830626ac3a Sebastian Thiel <byronimo@gmail.com> 1277806256 +0200 commit: Diff: fixed bug that caused a string to end up as a blob mode
58 6917ae4ce9eaa0f5ea91592988c1ea830626ac3a fd96cceded27d1372bdc1a851448d2d8613f60f3 Sebastian Thiel <byronimo@gmail.com> 1277999899 +0200 merge docs: Merge made by recursive.
59 fd96cceded27d1372bdc1a851448d2d8613f60f3 f683c6623f73252645bb2819673046c9d397c567 Sebastian Thiel <byronimo@gmail.com> 1278082451 +0200 commit: Fixed broken 0.2 documentation, it didn't contain the API reference previously due to import errors and a somewhat inconsistent working tree that occurred when switching branches ...
60 f683c6623f73252645bb2819673046c9d397c567 a4287f65878000b42d11704692f9ea3734014b4c Sebastian Thiel <byronimo@gmail.com> 1278092317 +0200 commit: win32 compatability adjustments
61 a4287f65878000b42d11704692f9ea3734014b4c ca288d443f4fc9d790eecb6e1cdf82b6cdd8dc0d Sebastian Thiel <byronimo@gmail.com> 1278517416 +0200 merge revparse: Merge made by recursive.
62 ca288d443f4fc9d790eecb6e1cdf82b6cdd8dc0d 5fd6cc37fd07c25cb921b77b4f658b7e8fc132b3 Sebastian Thiel <byronimo@gmail.com> 1278536545 +0200 commit: Adjusted clone method to allow static classmethod clone ( using clone_from ) as well as the previous instance method clone to keep it compatible
63 5fd6cc37fd07c25cb921b77b4f658b7e8fc132b3 76af62b3c5a26638fcad9a3fe401fba566fb7037 Sebastian Thiel <byronimo@gmail.com> 1278538933 +0200 commit (amend): Adjusted clone method to allow static classmethod clone ( using clone_from ) as well as the previous instance method clone to keep it compatible
64 76af62b3c5a26638fcad9a3fe401fba566fb7037 b425301ad16f265157abdaf47f7af1c1ea879068 Sebastian Thiel <byronimo@gmail.com> 1278539147 +0200 commit (amend): Adjusted clone method to allow static classmethod clone ( using clone_from ) as well as the previous instance method clone to keep it compatible
65 b425301ad16f265157abdaf47f7af1c1ea879068 3288a244428751208394d8137437878277ceb71f Sebastian Thiel <byronimo@gmail.com> 1278582561 +0200 commit: setup.py: fixed requirement - its interesting to see that there are two different keywords for distutils and setuptools, the latter one doesn't read the ones of the first one, unfortunately
66 3288a244428751208394d8137437878277ceb71f 08457a7a6b6ad4f518fad0d5bca094a2b5b38fbe Sebastian Thiel <byronimo@gmail.com> 1278670718 +0200 commit: Added python 2.4 support: Repo will now use the original GitCmdObjectDB in python 2.4, as the pure python implementation cannot work without memory maps
67 08457a7a6b6ad4f518fad0d5bca094a2b5b38fbe 258403da9c2a087b10082d26466528fce3de38d4 Sebastian Thiel <byronimo@gmail.com> 1278671744 +0200 commit: bumped verison to 0.3.0 beta2
68 258403da9c2a087b10082d26466528fce3de38d4 55b67e8194b8b4d9e73e27feadbf9af6593e4600 Sebastian Thiel <byronimo@gmail.com> 1278927490 +0200 pull gitorious master: Fast-forward
69 55b67e8194b8b4d9e73e27feadbf9af6593e4600 bcd37b68533d0cceb7e73dd1ed1428fa09f7dc17 Sebastian Thiel <byronimo@gmail.com> 1279007300 +0200 commit: Fixed incorrect use of Blob.data in performance test
70 bcd37b68533d0cceb7e73dd1ed1428fa09f7dc17 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 Sebastian Thiel <byronimo@gmail.com> 1279110447 +0200 commit: Added performance test to compare inst.__class__() vs type(inst)() class. The first one is faster, although I would have expected the latter one to be faster
71 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 a64c5f23c38f06c37a0ca64796368019dfb0d818 Sebastian Thiel <byronimo@gmail.com> 1279130658 +0200 commit: Correct Repo documentation in API reference
72 a64c5f23c38f06c37a0ca64796368019dfb0d818 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 Sebastian Thiel <byronimo@gmail.com> 1279130719 +0200 HEAD~1: updating HEAD
73 24740f22c59c3bcafa7b2c1f2ec997e4e14f3615 17a172920fde8c6688c8a1a39f258629b8b73757 Sebastian Thiel <byronimo@gmail.com> 1279131269 +0200 commit: Fixed the missing Repo type documentation thanks to a hint of gasche, fixed a few more resT syntax errors on the way
74 17a172920fde8c6688c8a1a39f258629b8b73757 cbb58869063fe803d232f099888fe9c23510de7b Sebastian Thiel <byronimo@gmail.com> 1279197254 +0200 merge gitorious/master: Fast-forward
75 cbb58869063fe803d232f099888fe9c23510de7b 89422841e46efa99bda49acfbe33ee1ca5122845 Sebastian Thiel <byronimo@gmail.com> 1279533542 +0200 pull gitorious master: Fast-forward
76 89422841e46efa99bda49acfbe33ee1ca5122845 192472f9673b18c91ce618e64e935f91769c50e7 Sebastian Thiel <byronimo@gmail.com> 1279814094 +0200 merge gitorious/master: Fast-forward
77 192472f9673b18c91ce618e64e935f91769c50e7 fa3fce80aeb57299633535b9e1c9d08db710ff05 Sebastian Thiel <byronimo@gmail.com> 1281701051 +0200 commit: unicode handling in messages and trees was improved. Messages are now written according to the encoding of the commit object, and decoded using that information as well. Trees will encode and decode their names with utf8
78 fa3fce80aeb57299633535b9e1c9d08db710ff05 394ed7006ee5dc8bddfd132b64001d5dfc0ffdd3 Sebastian Thiel <byronimo@gmail.com> 1281702078 +0200 commit (amend): unicode handling in messages and trees was improved. Messages are now written according to the encoding of the commit object, and decoded using that information as well. Trees will encode and decode their names with utf8
79 394ed7006ee5dc8bddfd132b64001d5dfc0ffdd3 c4d5caa79e6d88bb3f98bfbefa3bfa039c7e157a Sebastian Thiel <byronimo@gmail.com> 1283969691 +0200 merge integration: Fast-forward
80 c4d5caa79e6d88bb3f98bfbefa3bfa039c7e157a 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a Sebastian Thiel <byronimo@gmail.com> 1287134990 +0200 commit: Fixed bug in http://byronimo.lighthouseapp.com/projects/51787/tickets/44-remoteref-fails-when-there-is-character-in-the-name using supplied patch ( which was manually applied ).
81 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a fc650aa6869639548435ce2760d42c9cdd909d99 Sebastian Thiel <byronimo@gmail.com> 1287135891 +0200 commit: Added test to verify the actor class can handle unicode names correctly. This works because regex can handle unicode, and will return unicode instances instead of strings if required. Its quite amazing actually.
82 fc650aa6869639548435ce2760d42c9cdd909d99 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a Sebastian Thiel <byronimo@gmail.com> 1287136504 +0200 HEAD~1: updating HEAD
83 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a a88173281ec56cb378a293d0170e11a1bda96a55 Sebastian Thiel <byronimo@gmail.com> 1287138898 +0200 merge unicode: Merge made by recursive.
84 a88173281ec56cb378a293d0170e11a1bda96a55 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a Sebastian Thiel <byronimo@gmail.com> 1287139082 +0200 HEAD~1: updating HEAD
85 741dfaadf732d4a2a897250c006d5ef3d3cd9f3a 13647590f96fb5a22cb60f12c5a70e00065a7f3a Sebastian Thiel <byronimo@gmail.com> 1287139254 +0200 merge unicode: Merge made by recursive.
86 13647590f96fb5a22cb60f12c5a70e00065a7f3a 94029ce1420ced83c3e5dcd181a2280b26574bc9 Sebastian Thiel <byronimo@gmail.com> 1287139994 +0200 commit: Adjusted regex to support whitespace - it was a little restrictive previously, although there was absolutely no need for that.
87 94029ce1420ced83c3e5dcd181a2280b26574bc9 8858a63cb33319f3e739edcbfafdae3ec0fefa33 Sebastian Thiel <byronimo@gmail.com> 1288000691 +0200 commit: .gitignore will now ignore netbeans projects
88 8858a63cb33319f3e739edcbfafdae3ec0fefa33 a2b9ded87baf0f32ae94c10c5851a0468a45f003 Sebastian Thiel <byronimo@gmail.com> 1288198935 +0200 commit: docs: untracked_files is a property, but was used like a function, see http://groups.google.com/group/git-python/browse_thread/thread/84ed1835e26a5296?hl=en
89 a2b9ded87baf0f32ae94c10c5851a0468a45f003 8858a63cb33319f3e739edcbfafdae3ec0fefa33 Sebastian Thiel <byronimo@gmail.com> 1288198984 +0200 HEAD~1: updating HEAD
90 8858a63cb33319f3e739edcbfafdae3ec0fefa33 148eb761aeaa4c3913e1766db0a7df0a5b5c8b20 Sebastian Thiel <byronimo@gmail.com> 1288198991 +0200 commit: docs: untracked_files is a property, but was used like a function, see http://groups.google.com/group/git-python/browse_thread/thread/84ed1835e26a5296?hl=en
91 148eb761aeaa4c3913e1766db0a7df0a5b5c8b20 8858a63cb33319f3e739edcbfafdae3ec0fefa33 Sebastian Thiel <byronimo@gmail.com> 1288199023 +0200 HEAD~1: updating HEAD
92 8858a63cb33319f3e739edcbfafdae3ec0fefa33 538e8265e04f69bb9bd73a10ddb4e8e9677fb140 Sebastian Thiel <byronimo@gmail.com> 1288199049 +0200 commit: docs: untracked_files is a property, but was used like a function, see http://groups.google.com/group/git-python/browse_thread/thread/84ed1835e26a5296?hl=en
93 538e8265e04f69bb9bd73a10ddb4e8e9677fb140 97ab197140b16027975c7465a5e8786e6cc8fea1 Sebastian Thiel <byronimo@gmail.com> 1288203452 +0200 commit (amend): docs: untracked_files is a property, but was used like a function, see http://groups.google.com/group/git-python/browse_thread/thread/84ed1835e26a5296?hl=en
94 97ab197140b16027975c7465a5e8786e6cc8fea1 3da3837fe2ec8152e1460f747d18290b52304868 Sebastian Thiel <byronimo@gmail.com> 1288203532 +0200 commit: cmd: improved error handling and debug printing
95 3da3837fe2ec8152e1460f747d18290b52304868 2c0b92e40ece170b59bced0cea752904823e06e7 Sebastian Thiel <byronimo@gmail.com> 1288203543 +0200 commit (amend): cmd: improved error handling and debug printing
96 2c0b92e40ece170b59bced0cea752904823e06e7 1b6b9510e0724bfcb4250f703ddf99d1e4020bbc Sebastian Thiel <byronimo@gmail.com> 1288205467 +0200 commit: Fixed bug that would cause the author's email to be a generic default one, instead of the existing and valid. The rest of the ConfigParser handling is correct, as it reads all configuration files available to git
97 1b6b9510e0724bfcb4250f703ddf99d1e4020bbc 0d5bfb5d6d22f8fe8c940f36e1fbe16738965d5f Sebastian Thiel <byronimo@gmail.com> 1288208986 +0200 commit: index.reset: updated parameter docs, but most importantly, the method now has better testing for the use of paths during reset. The IndexFile now implements this on its own, which also allows for something equivalent to git-reset --hard -- <paths>, which is not possible in the git command for some probably very good reason
98 0d5bfb5d6d22f8fe8c940f36e1fbe16738965d5f 735b28bc65964da5b181dffcccb1d05555b5acab Sebastian Thiel <byronimo@gmail.com> 1289033220 +0100 commit: test_refs: fixed failing tests just by making it less strict. It is dependent on the setup of the surrounding repository, hence the amount of ref-types found is actually variable, as long as they get more
99 735b28bc65964da5b181dffcccb1d05555b5acab bd7fb976ab0607592875b5697dc76c117a18dc73 Sebastian Thiel <byronimo@gmail.com> 1289034759 +0100 commit (amend): test_refs: fixed failing tests just by making it less strict. It is dependent on the setup of the surrounding repository, hence the amount of ref-types found is actually variable, as long as they get more
100 bd7fb976ab0607592875b5697dc76c117a18dc73 a1d1d2cb421f16bd277d7c4ce88398ff0f5afb29 Sebastian Thiel <byronimo@gmail.com> 1289379557 +0100 commit: tutorial: Fixed incorrect initialization code for bare repo, thank you, Bryan Bishop
101 a1d1d2cb421f16bd277d7c4ce88398ff0f5afb29 f1545bd9cd6953c5b39c488bf7fe179676060499 Sebastian Thiel <byronimo@gmail.com> 1290118292 +0100 merge submodule: Merge made by recursive.
102 f1545bd9cd6953c5b39c488bf7fe179676060499 45c0f285a6d9d9214f8167742d12af2855f527fb Sebastian Thiel <byronimo@gmail.com> 1290122860 +0100 merge docs: Merge made by recursive.
103 45c0f285a6d9d9214f8167742d12af2855f527fb 315c303214cef855499f0c7eda46b7ed82dceecb Sebastian Thiel <byronimo@gmail.com> 1290158850 +0100 commit: test_submodule: fixed failures that arose due to changes of the original submodule names. Also, a major bug was fixed that cased submodules to always being updated recursively when using the RootModule.update method
104 315c303214cef855499f0c7eda46b7ed82dceecb 7dd618655c96ff32b5c30e41a5406c512bcbb65f Sebastian Thiel <byronimo@gmail.com> 1290158895 +0100 commit (amend): test_submodule: fixed failures that arose due to changes of the original submodule names. Also, a major bug was fixed that cased submodules to always being updated recursively when using the RootModule.update method
105 7dd618655c96ff32b5c30e41a5406c512bcbb65f 2ab454f0ccf09773a4f51045329a69fd73559414 Sebastian Thiel <byronimo@gmail.com> 1290188727 +0100 commit: remote: parsing of fetch information now reacts to fatal errors. Previously it would just bump into an assertion
106 2ab454f0ccf09773a4f51045329a69fd73559414 b00ad00130389f5b00da9dbfd89c3e02319d2999 Sebastian Thiel <byronimo@gmail.com> 1290196658 +0100 commit: submodule: When adding an existing submodule, when retrieving the binsha, we will now consider not only the tree, but the index too
107 b00ad00130389f5b00da9dbfd89c3e02319d2999 8867348ca772cdce7434e76eed141f035b63e928 Sebastian Thiel <byronimo@gmail.com> 1290196804 +0100 commit: Bumped version number to 0.3.1
108 8867348ca772cdce7434e76eed141f035b63e928 8d0aa1ef19e2c3babee458bd4504820f415148e0 Sebastian Thiel <byronimo@gmail.com> 1290271885 +0100 commit: Fixed performance tests which broke in the meanwhile - they definitely don't run often enough, which is because they intentionally don't have a package initialization file
109 8d0aa1ef19e2c3babee458bd4504820f415148e0 8e0e315a371cdfc80993a1532f938d56ed7acee4 Sebastian Thiel <byronimo@gmail.com> 1290280591 +0100 commit: submodule: Fixed capital error when handling the submodule's branch, which was returned in the submodules super repository, not in the submodule's module
110 8e0e315a371cdfc80993a1532f938d56ed7acee4 7c72b9a3eaabbe927ba77d4f69a62f35fbe60e2e Sebastian Thiel <byronimo@gmail.com> 1290286993 +0100 merge gitorious/win32: Merge made by recursive.
111 7c72b9a3eaabbe927ba77d4f69a62f35fbe60e2e 517ae56f517f5e7253f878dd1dc3c7c49f53df1a Sebastian Thiel <byronimo@gmail.com> 1290288333 +0100 merge osx: Merge made by recursive.
112 517ae56f517f5e7253f878dd1dc3c7c49f53df1a 22a88a7ec38e29827264f558f0c1691b99102e23 Sebastian Thiel <byronimo@gmail.com> 1290289085 +0100 commit: fixed performance tests ... again, previously I was just working on an incorrect repository
113 22a88a7ec38e29827264f558f0c1691b99102e23 685760ab33b8f9d7455b18a9ecb8c4c5b3315d66 Sebastian Thiel <byronimo@gmail.com> 1290342054 +0100 commit: Added zip_safe info to setup.py file
114 685760ab33b8f9d7455b18a9ecb8c4c5b3315d66 9d6310db456de9952453361c860c3ae61b8674ea Sebastian Thiel <byronimo@gmail.com> 1290342681 +0100 commit: docs: added final docs for version 0.3.0, started new release 0.3.1
115 9d6310db456de9952453361c860c3ae61b8674ea 0b813371f5a8af95152cae109d28c7c97bfaf79f Sebastian Thiel <byronimo@gmail.com> 1290358083 +0100 commit: Fixed API reference docs as far as possible
116 0b813371f5a8af95152cae109d28c7c97bfaf79f 94140bbfc523ae13e1e8045ebfed8a76fe0a1872 Sebastian Thiel <byronimo@gmail.com> 1290372438 +0100 merge structure: Merge made by recursive.
117 94140bbfc523ae13e1e8045ebfed8a76fe0a1872 d01b428dbac4103b4f7d7b8fca32e01f70746c53 Sebastian Thiel <byronimo@gmail.com> 1290372442 +0100 commit (amend): !!WARNING!!: Directory structure changed, see commit message for instructions
118 d01b428dbac4103b4f7d7b8fca32e01f70746c53 db3423d1eab11d00c5475e36eae8952512b07f4e Sebastian Thiel <byronimo@gmail.com> 1290373147 +0100 commit (amend): !**WARNING**!: Directory structure changed, see commit message for instructions
119 db3423d1eab11d00c5475e36eae8952512b07f4e 5ed5b2011ec7cf72f19e6d53b588eea4adca68e5 Sebastian Thiel <byronimo@gmail.com> 1290373168 +0100 commit (amend): *!*WARNING*!*: Directory structure changed, see commit message for instructions
120 5ed5b2011ec7cf72f19e6d53b588eea4adca68e5 470d4a7cc865d2702c326d9d1d1b0ab7afb49f0e Sebastian Thiel <byronimo@gmail.com> 1290373186 +0100 commit (amend): !##WARNING##!: Directory structure changed, see commit message for instructions
121 470d4a7cc865d2702c326d9d1d1b0ab7afb49f0e e088424eb01bd47c6f0d313f465a21ee742e6f4a Sebastian Thiel <byronimo@gmail.com> 1290373209 +0100 commit (amend): If you use git-python as a submodule of your own project, which alters the sys.path to import it,
122 e088424eb01bd47c6f0d313f465a21ee742e6f4a 48a17c87c15b2fa7ce2e84afa09484f354d57a39 Sebastian Thiel <byronimo@gmail.com> 1290373245 +0100 commit (amend): -#######->WARNING<-####### Directory structure changed, see commit message
123 48a17c87c15b2fa7ce2e84afa09484f354d57a39 fca367548e365f93c58c47dea45507025269f59a Sebastian Thiel <byronimo@gmail.com> 1290374761 +0100 commit: Changed version to 0.3.1 (removed beta1) so that other projects can actually depend on git-python using the setuptools. Previously it would claim the version did not exist, probably because the setuptools are just comparing strings
+0
-3
git/test/fixtures/rev_list less more
0 4c8124ffcf4039d292442eeccabdeca5af5c5017
1 634396b2f541a9f2d58b00be1a07f0c358b999b3
2 ab25fd8483882c3bda8a458ad2965d2248654335
+0
-51
git/test/fixtures/rev_list_bisect_all less more
0 commit cf37099ea8d1d8c7fbf9b6d12d7ec0249d3acb8b (dist=2)
1 tree 01fb5ddba393df486d850c37f40c9a87f4a28a14
2 parent bfdc8e26d36833b3a7106c306fdbe6d38dec817e
3 author Florian Apolloner <florian@apolloner.eu> 1218480521 +0200
4 committer Florian Apolloner <florian@apolloner.eu> 1218480521 +0200
5
6 use shell=True in windows (git.exe needs to be on %PATH%)
7 One bug remaining: git on windows is returning status 0 for `git this-does-not-exist`, so no GitCommandError is raised.
8
9 commit 33ebe7acec14b25c5f84f35a664803fcab2f7781 (dist=1)
10 tree 960b40fe368a9882221bcdd8635b9080dec01ec6
11 author Michael Trier <mtrier@gmail.com> 1210193388 -0400
12 committer Michael Trier <mtrier@gmail.com> 1210193388 -0400
13
14 initial project
15
16 commit a6604a00a652e754cb8b6b0b9f194f839fc38d7c (dist=1)
17 tree 547e8af2f10ffa77c4ed4d0a8381e64141f986b4
18 parent cf37099ea8d1d8c7fbf9b6d12d7ec0249d3acb8b
19 author Florian Apolloner <florian@apolloner.eu> 1219330141 +0200
20 committer Florian Apolloner <florian@apolloner.eu> 1219330141 +0200
21
22 fixed unneeded list unpacking
23
24 commit 8df638c22c75ddc9a43ecdde90c0c9939f5009e7 (dist=0)
25 tree 43a63b045e538a38161c8da5e154ff1c9436ea4e
26 parent a6604a00a652e754cb8b6b0b9f194f839fc38d7c
27 parent 127e511ea2e22f3bd9a0279e747e9cfa9509986d
28 author Florian Apolloner <florian@apolloner.eu> 1219330182 +0200
29 committer Florian Apolloner <florian@apolloner.eu> 1219330182 +0200
30
31 Merge branch 'master' of git@gitorious.org:git-python/mainline
32
33 commit c231551328faa864848bde6ff8127f59c9566e90 (dist=-1)
34 tree 991ed402b4f6562209ea56550a3c5050d1aa0118
35 parent 8df638c22c75ddc9a43ecdde90c0c9939f5009e7
36 author David Aguilar <davvid@gmail.com> 1220418344 -0700
37 committer David Aguilar <davvid@gmail.com> 1220418344 -0700
38
39 commit: handle --bisect-all output in Commit.list_from_string
40
41 Rui Abreu Ferrerira pointed out that "git rev-list --bisect-all"
42 returns a slightly different format which we can easily accomodate
43 by changing the way we parse rev-list output.
44
45 http://groups.google.com/group/git-python/browse_thread/thread/aed1d5c4b31d5027
46
47 This resolves the issue mentioned in that thread.
48
49 Signed-off-by: David Aguilar <davvid@gmail.com>
50
+0
-8
git/test/fixtures/rev_list_commit_diffs less more
0 commit 91169e1f5fa4de2eaea3f176461f5dc784796769
1 tree 802ed53edbf6f02ad664af3f7e5900f514024b2f
2 parent 038af8c329ef7c1bae4568b98bd5c58510465493
3 author Tom Preston-Werner <tom@mojombo.com> 1193200199 -0700
4 committer Tom Preston-Werner <tom@mojombo.com> 1193200199 -0700
5
6 fix some initialization warnings
7
+0
-8
git/test/fixtures/rev_list_commit_idabbrev less more
0 commit 80f136f500dfdb8c3e8abf4ae716f875f0a1b57f
1 tree 3fffd0fce0655433c945e6bdc5e9f338b087b211
2 parent 44f82e5ac93ba322161019dce44b78c5bd1fdce2
3 author tom <tom@taco.(none)> 1195608462 -0800
4 committer tom <tom@taco.(none)> 1195608462 -0800
5
6 fix tests on other machines
7
+0
-7
git/test/fixtures/rev_list_commit_stats less more
0 commit 634396b2f541a9f2d58b00be1a07f0c358b999b3
1 tree b35b4bf642d667fdd613eebcfe4e17efd420fb8a
2 author Tom Preston-Werner <tom@mojombo.com> 1191997100 -0700
3 committer Tom Preston-Werner <tom@mojombo.com> 1191997100 -0700
4
5 initial grit setup
6
+0
-655
git/test/fixtures/rev_list_count less more
0 72223ed47d7792924083f1966e550694a0259d36
1 f7cd338ee316482c478805aa8b636a33df3e4299
2 994566139b90fffdc449c3f1104f42626e90f89f
3 e34590b7a2d186b3bb9a1170d02d52b36c791c78
4 8977833d74f8681aa0d9a5e84b0dd3d81519774d
5 6f5561530cb3a94e4c86454e84732197325be172
6 ee419e04a961543444be6db66aef52e6e37936d6
7 d845de9d438e1a249a0c2fcb778e8ea3b7e06cef
8 0bba4a6c10060405a94d52533af2f9bdacd4f29c
9 77711c0722964ead965e0ba2ee9ed4a03cb3d292
10 501d23cac6dd911511f15d091ee031a15b90ebde
11 07c9bd0abcd47cf9ca68af5d2403e28de33154f1
12 103ca320fc8bd48fed16e074df6ace6562bed4b5
13 55544624fb9be54a3b9f9e2ec85ef59e08bd0376
14 e5c8246dec64eccad0c095c67f5a8bbea7f11aca
15 1b54d9f82ee6f3f2129294c85fad910178bef185
16 36062a1634fb25de2c4b8f6b406ae3643805baf5
17 0896bb9b8d2217163e78b5f1f75022a330d9ddc8
18 6646dfce607b043ab7bbe36e51321422673b7c56
19 f0bad592abc255fabe6c6d6c62b604b3de5cdce2
20 5705e15c71f9e10ca617c0a234b37609cfb74d23
21 b006d8b73912eb028355c49e7bfe53a29f97ce7c
22 b21eb6173dbe07cac63f4571e353188dde46f049
23 a3256f3150ccec73c50b61b85d54e30e39a65848
24 c5a32e937166d65757f3dd4c1b6fd4f5ecc10970
25 1e90e2c654aab0d81088f615c090d6d46f03ca4c
26 924e7685fcd62d83aac19480837e4edd9c4bae5e
27 489e1468aea658a333481132957069708127c69f
28 970b6b13726889f6883e4347e34d8f9d66deb7c9
29 df74c45e8fdb4d29a7de265ac08d0bff76b78a83
30 936aa0b946155b2d47528073433fc08b17a4c7cc
31 3b6a5e8f12b6269a0a3e0eaeede81abfb3fc4896
32 8e0f306dae96d78aa1ea9a08e82647fd95fc1a74
33 5eb099e5e274be44c0fd27ce8928d2dc8483dab7
34 050fbed693d4806ac6c03460103777b2a4befcf8
35 c5d4b6dac74e323d474fa8878a7ea0c233d57019
36 8e5daf911943d5ef025025c137fcf97164467141
37 bcdf7c2421302b15f4ee4ebbdeae7b644a4518e7
38 e2874a42835cbb2fe8856a398f5c4b49a9cd8d30
39 f50ea97159e4ae7132e057fbf5ea1e75ec961282
40 5dbd614c20e9473240082239894d99c24de42282
41 0490e1ac1ffafcb9117029286b224ab39671a015
42 ad3620d47f0ea96f24904227d3c7a7f9548c34dd
43 fd37e7191ae3d312ced0877a1492cd2ea4578275
44 b7f8cc51c9056a469006b5601a4993b67c07e099
45 1d849af5083073b8864487938a9a2a8e21d71529
46 26d0bb4c9ee3d8591fe291c86f495b2d1900bf9b
47 7a25e3056a7225c1ff8542c2c2c1cf6f3a8e13d4
48 d0e0de0b13b9c81d2bcf9d54eecdb20591fd6d2f
49 0bf82343ade1e07c0aebd14ee66df688a4cc0e87
50 d81de0fb6a19342a90cdba9a664659da66296162
51 9105667175797bbadea80879e98a5cf849a40065
52 12f5af2a169c658cfae1677ceafd527d3775873f
53 00ae94689600b5949bd0fcf68205f31f95a36aa4
54 8f5d34224e4620c51c16c01578786e76567d025d
55 3385eb31651c84384b4c7e93d82bc5b592edf9fb
56 eda9179b9af0275d62c4074480e7a0103d356435
57 982c2d1e55165fddb4f4c69065e2c4ac39542c84
58 7117495ef012719769582939ea59a5533077fc8f
59 b7dae75dab5b59a320b8df8a67060d238fed3a8e
60 37c684e1a46599fe4d34d1601875685a70b1b879
61 0a694fa0cb044a31bb844564776b490c151ac317
62 e77c6b459f01ce078aa59183189226a6d48fdf38
63 dd0c0eaefdebc38610bb1986e51324a0392e829a
64 d8bc2414e9504172da640f29db1b2d29d834a94b
65 a9f1119667dd0f5aa9413dec23965a747d1dac05
66 f52775f6bc21d999382f4b9b38b108b814114ea1
67 e82c77ac679887140867e471a9f47fd3b2d95039
68 2db3fff5673bbd4bfcc8139d8398727d243c9efd
69 c1805c000c6233a20ac0824cad21c1fe40f93100
70 83f7807585cf70018a9a06179af9d89d4a8204b2
71 730c326beb29cc6d2624915b125633792a40ca36
72 bea422b653d74dd03ec068dcce938169149aa822
73 586a57666618299464519c450033eecc3ce89664
74 82fba8cf4796f2adbec5ad336bd750ad60a075fd
75 9d9b899f836a199fe854075e99091d1ef083de24
76 4670357c662596aa2c2922d826de84abd9f877ea
77 9b562567430544c74009ea4a6173f44ddb4a44e5
78 013d51fbb5f3a60bc748449b1ab73158da9a3203
79 3fe67cb90fca9ea76292deb793cb480f4eb5e8d6
80 91c80e489fee08e71a79bfbea79fcc28e1aa27f2
81 dd9104095bdb08fe399af46d91b334e760986ddd
82 a9198904586546a038f855bc6fc0e7cc413722fb
83 574a7bad1017d9ed466474881e1f068f892207f4
84 f95acec9297b7816284d8b24e984cd5c82104c89
85 3907dac65a125b7759172a8eae959b0e70220299
86 e5b44576eb2182b16c7b6770fab5977eedbc03c6
87 9f4aad9833d0f9a609dd2556e7db784ba813d8fa
88 579309c96651a1fed75fdd18f80019db8e6624ec
89 5e1a9a48e6c96099d6a0c3aff1e31c9be16b7b8d
90 cae4b811038f4e0dd4a8e68122c3db955e10ae81
91 fccee1c818f5af5fce593de0949f5a8ecd35b443
92 d4187d5a5f9ffe1f882c74f6ced7e0ba1c260ff2
93 02ff197aa41d892e623dc668b0055806294bd6c0
94 3f81af24214761a6ed77fd4dcd6e45a651dd8f84
95 5cb08c5232a669a881606a6d8c4a4cd23aad6755
96 5212b25869e0b9aff485af6f5371a159e89f8f07
97 a778322bb60f8438a68112a73df78e05a97093ff
98 b55c30c3992a766628dfc4a7e22db4d8d9e46b5f
99 1d3e4a32e0407f16f641be316c745c1a48f16e2b
100 7f35ca3333944165e0ec82a3a95c185f67fba904
101 ef6c5bbe2dffe76e4a9698df03b8ee08af702033
102 aeb90405ed696c1efcb29d0664b43a52a2bf824f
103 e0b8bebd78172229666dfd425933f9bc21863928
104 2a71a55154edf75ab51dcb4f2f7dc63592410e16
105 a5d25352d326c77d083a2e089c2d80b4ea923624
106 a3fbc38b9f1b86bb5f5e6540048083fc1dc6062b
107 bbe67e1bdadf4aff186769145a40727f78e39e01
108 a02a58c6c6d04001873ba91ac3dc902275879d0f
109 eb5281d4f40e18b0e21d275ee5c5964bbbcc855c
110 19e9939a098b9cb93c8c1d0d069d46861afb507a
111 7a72471f9a4587cc4a7d37da0d26122b0eadaddc
112 c6a043eb057cd544130b77bf99f39b7738e0a204
113 723b6223726c6772e034d9f4ba5c710e66a1991f
114 25b4ff1a26dd3694a98c1ef2eba04a5a500c0b28
115 7c571ac2c35a7e1f399651242e904596c93beeb0
116 0c90015733521720688bfcb59ad2a3978b2fbbc3
117 d6b99183122a97a590e4e54f4617b58f13b90df8
118 6b663271af39d69082422866e61ff7801c2b3fa7
119 2e9e6ab7651e4c215110eb381678e0ea2bc0f7d8
120 967b91e045661c9b6d2a5f011ec152da391db7ec
121 7fda8d15bdb3d3d61fce49413153a216849721f9
122 f7d7e83ee1cec103a768ddc9f68b6d5075849894
123 925953da542a9c21a3fde1ab0891175fb6212a12
124 ea2f54455427506583437391cbaf470a1ef4edeb
125 f0bdb2cdddefb3a391ec2e3fa9b78ed06d7c874a
126 8d289566fa92a96a83ff3c2e24c1f3d12b1718ed
127 7fb102615532952c6833e87389668831b37a13d6
128 7f7bbe8473158ab606a89ad66d607ffd0e5ba1f7
129 a98ea5a00d19406f3e644448039f13db496cefd5
130 39f03072d9d84d622ae974b09dd11cf7a2515a7c
131 e2050a1c488fff4b114614d7f75096dd0a149f5b
132 d2851f113530fbe211b3e948b6181152d30d1fa3
133 1eef0fe740f6db35a91e790fe77d4ba1c9065e99
134 9608403b012908cc58223db44962553704cab8af
135 4911a005ea6b55f34f8b0f504a6a0934c0df896a
136 a4400fb8e7d0f1261634dbb89588da86b8b6c93f
137 f310729583f6733ee60f534a9732b7a3a9e414d4
138 49e78793487ce4d8d7e624b5245fca8a9cc1ba66
139 2f2501ce5d28e5ada6018504ee8dcecbbee70428
140 f1e127253e1eb07b537b221e9cc96beb16333790
141 8bf1684ca9b5a37d91671dd0d63d0ac59bea987a
142 24838a6042a134b11fe945bbaa5ab1b2b3fc6eb0
143 f53c57af21fded3735fd479b3785fcf7adf80268
144 aa8d0a63d61d13524b1395972563b516cd263f05
145 16803d64332412a66121ef3fd10cd0d88598d3be
146 5f2715ed4d9416fa4940c2cd29b5ca18b6a79b8c
147 851ede1f8dceef7d681f35e4769e5693160c0a04
148 5264588c6c20c38d54394059eef0a854683aa3fc
149 111800d8e66ff86f0757df7eb6533fc62040a22f
150 b04de89d31003e468c191cd08dd2a4629d99c38e
151 6aef629094e9ee6b4fac2431897844c4dddf2f57
152 d1168c999fdae7d1eaac8c163b2b1190afb1815c
153 6afc3257929528d9f4de964e8828822d2fa2c93a
154 436f30ce1b562efe4f34696def45b0145eb98304
155 9afbf904be0e6154f6c424377ad596e86ea38807
156 a3cf657305d9283525711e867e03684a2e4b39cc
157 5813b4d04b25c385359af4437027b4fe763cd2ba
158 0fa594594c97a0d3579312f4ec073304c1436106
159 cb7b36c28adb38b1e597fa3f3b5c24c988a25b0e
160 5b0c867cbda81ce34df1b5fb67557b556ea24e9e
161 44090e9c550c7c5ded01dc2a681a7c934ba901b6
162 9ccc89b61736c4a9c02faaa679e97a9ec063dd29
163 7828d6d18115b0720888a45e3b547b697910c59e
164 618497e48e46fdc00dee67c07cd0f40860e819f9
165 69a14ed4f36d880e8322a530d8c5bfd9888a8c13
166 0a0cd655e40903abff4840c23b57628fb1a88122
167 cb262098646f47e1d80a89662f1480c216bfd81b
168 d60e59fce6f698a8bb97e2b4a935c069584621b1
169 ca77ba0d6d301cee1d45edb24742dc5cdabd4b83
170 17b598510967922690f5181903f20ddae5758e86
171 30ad3d9f3164966afb2974640f772387fb796b7d
172 48964c5dcc94234dea1737d7fa23220f9eab0fb7
173 0fe241f4db12f455c2f5976c6bf6497cc485f503
174 04953aca41bd372d990da7f68cc795f4a8b78d94
175 2dc9a061595a291d8c53168c42da8d14da52d610
176 68b15d34903038e3f2e327f03f0486b2d38784bc
177 30ceaaf39b10f9f9c7b4362505144d1650035a40
178 e75891a5760f6a51f54a33b671951c16fbce1558
179 b2a35989ad3392f26e070b158f89d1d8b75327f2
180 8468830b8b37f7c1cdda926a966c0aba2893a7c0
181 6a6112e8cde1bafebfa12e4c863dab5834c38e12
182 eafcd2ffc25d17fce41eff2afd5c4521730a23ab
183 f7eda0752f45c3a4eb13e075b24b86d7e7dd5016
184 b634d0d48d0a113bc060a47972b10c9353621428
185 49f95235a174f0a056e44bb5c704fea4ab345353
186 6eec70a31a6376ffd7d6b143be0968a195ad59d6
187 7c9ae1a71aa39efe28a678c18c8a03d759deabed
188 a19fd6f13c16720dc38a1f572eebf960022015ad
189 87052ac2cbaec195094e1d1a2bad4ac480bd111e
190 2cde1b0e69f97a8a67bb47d729c53af3ba8e5700
191 91a06d1a4efb6376959c3b444a536fe6b4fd4d6b
192 07f73b465b6c509b337c2776fe7a73b56ee178ec
193 15218bab55236d62fb8b911c2ae1ee05dde1ee60
194 900180ff2aa70e7d857403412753df6384553d26
195 a9c43cbeb0542cf6538fe8025edc8863d2526c68
196 d7d8f0c9b7d56f554d5a5cf5759f30cc3d36771c
197 d703e5d9ac82b8601b8f4bfe402567b5ce3ebbf9
198 3905a12ad511ffe157cb893e7769f79335e64181
199 73a933454b09ee48ffc873b0ee767e0229f2d609
200 c2c91403aa9d95efa09843bffe83ace4d52d3446
201 c90f480010097efa3fb7046abe7fac3c9b8b3975
202 13e888d5624e8087ea63638de7f4375f5c13ac55
203 19344e551c8c5e56e91de14253b4f08ca05f9e69
204 b1b8f098bb1e2f0f08cf82805d7bd29d2931f63e
205 3a3e025bbb2f3e49facac00e270d8afa5d31b962
206 195116405307f7bd9575f9621fd93344304341d1
207 31252094210748399f7e43e7b6149190990f4e8c
208 357e549bf43126e371a1f85c393d2560597cb32d
209 df1f8ab23f915420e9c48744decbc45375f180d3
210 f96c2eedf6800b8fc31032a02caf0d2b469ba9ec
211 73405f0505813ec1bd25f03f2825315f3520bcca
212 7e2447536c35ae67e3737a031fa1ac57026475a0
213 970d4c4854dbcc3b0bf9b16edf1d47eabf3be242
214 3c73519e6b54d3559555ffac40072957041f62d4
215 46d461676fc1fb16fd7dee027065441d9a8b87d5
216 f11f64bb55240dcc1767a1ec823aecd3531f1d20
217 038e91a424078c5d81cba6c820cd981f0be6086b
218 157d6e98ba894cba5582caeb15b429ca0dcbf2d9
219 2c768cf9d1bdb6d3d84f662a847966b69c898f59
220 4fd0f29459ec3ea65625b943b147df85e5826cd9
221 c7e90c64e580ce5f95147eb4e117b56b5cda254b
222 cd4f2496b274b0d55b7c48388c2ec0365d9bc266
223 68b5e288a29ebbcd65e6d0a8eed47702ee4e689c
224 22abd4a7ed7b061364e002f1fe08857850a309ad
225 4c3b38be6fda8ba32fe6f29226539e03bd0c55ce
226 355e946ca8b8a5e4c17317446b12fc374399810a
227 1fc5c0122fffdada1630febc1f2e42952cdc7e2e
228 8db042e1faef7be24d62b9287fd3b9add7a1b4cb
229 1cbea023ce354939ae9082a62810b46f38ab1cd8
230 f5edf5b99d1bae09314b9680e58766a4e3c1bbc0
231 58a5ef79958b58736603f47cf211494fe5819601
232 8f2038bec169ae6d62885f522202d8171e3f5f5c
233 5488e29e68684648b4d733e90c6e3188d3bd5bad
234 84c88e813117db46c6ac68b16a7739018eb99e24
235 789c3655197585ba8771ce68c0117cbdd41ea390
236 0510404a3c0d337763e90e5315548043bac65b06
237 2a665d7c6cab59ea8e3bb7fc65249ee947e51fec
238 d53423de534d3b5e68a7644d4218d835a8bfe6ce
239 73f2a3f332f23579a29e090f70825dcf84dcdbac
240 f79ae7f27e750c97c139cdbdd7c3223b39ed1a70
241 c84a75f7a4b274c5c133b1df3648a5a24ed9f687
242 cdf8e5a49192b81bcd39d9f4e39aa4812b58b80c
243 1180461f564674e373222fec3b4fe8c2861ea6a6
244 150d93bd910597b85500e74b97b96e7eb4bce2f6
245 ec3b819ffe3392bf193483fea94d4404c88966b1
246 729fc8ffd38c02a9576640b56376c36b49edf52e
247 2ee31128fbd86244d547e3ff66b802dda699210f
248 f87f28c563ad602cba605e84bee95693b77b8840
249 9e92c5fb59af58867acf5512e95138fc368f7dae
250 76b1489042e1bb45909832f7064f9a5437b68b18
251 66f5d86face564c095b3c95848f070f50fe4688a
252 f9b2b3ec52b88dbd68b2f2c6b246bf07f632b40c
253 14f689f05c4fae52ac8bb95762ff43b9f7f4e567
254 5ca84af5f7a3f4533b353c43a332b552cb2fc5e4
255 c5f33e9eb55201c41691e14fff0d45e32c989a42
256 9f83cf471949164a6352cb9e3a201b8bb317b89a
257 5532c7b06a2f02e9cafd6673d5099798c4144690
258 0d28c20ab4f03b5d8579132048c060affc36c466
259 cddce1dfd9d4d7f1fc49003aa211f018bf8fad2a
260 169617e3672bac804a271c0aaff9cdbac7b4b45e
261 fdebb28d6ae398ccba88f3e2e63ef6d7f10f62f4
262 0651bfe384a8d5865d6cab808ca0ce803af93878
263 de89eb007459fd5400cd344dddf240fc33fd0b65
264 c6a14beb887170d8c901e522f2f4dce3bf0b9ed8
265 13dd0647b3ee39fae1140f8eff2b15d7f63ee546
266 9f89105c1462f2a80e620ada1b95c3d08a121c3e
267 1ed6496751273cf472538779266dcc3dc9797192
268 4e8dffa66fc7be8f864cb48cf26abcef4cc32379
269 5543fce145ff28a1c424b730b376fd4e3cfa0956
270 bd951a4a8574baac21b7e1f3a09d1265aa51850a
271 3fd1c12fa880ee45b0ff7b794238a8894306a790
272 830ec14bc9edbd2c6522ff46ed0acfe477e7e32a
273 e68c3109a709e2b732d0945f860495de161754a2
274 1e0f4fda735167ff6d27c76a67b8b4a4ab31aaf6
275 c6c40dd0ff4420708c2e0f5a0e0dadde93eae336
276 baf0c18ac24acb9ac3d1a7c0030ad5675eeb64d7
277 8d30906e9f2f68024eb716be9f482de5cec5b302
278 ec9fce551828795e1dace26a11f57f9aaf1af37a
279 28fb918d7e9840a7118b7aa0b6151b496f1fc1f0
280 b9e58c5b98f7c89054ed5c0a0226066ba9d93c8d
281 0c5db457cdd3852182ce70b96cb376337b8ad7ad
282 36a48168274cbb6f31c35777a74ee16c06e1a853
283 07ef3ad40bb01bc7798b241c88fda2eaba7aad19
284 02aa9f2ba871e9639891986a97618e0917955fc8
285 5f776d3c74ad532f36ab75a71bcbece6a62c831d
286 f31ea9eeea91106481e1b2d30026b601555b6699
287 c3d7f6bac18fbf8041662fbdda4f04e3f3b25e3a
288 6280c4bcf1195c011d7a7abb5bf689df11d66419
289 45fc4ef9adaf514bbe21f496cdea8869a147c81b
290 fa1160786e34c057cf1212efd59a72c3931eb2a3
291 09b285cc7d7c8768917c7d4e5513e3e73d752b68
292 a8da5db6094c887f1087162c5ddfddf601560523
293 b6134a31d236c376193e969a2df65c8427d280a0
294 793e0d19fef38f8a151622257b13edf6786e469e
295 e40e6a17b4df5be46a2cafaa3fca5f4c3cec5001
296 4d82e160cb874da6dbddc27af7dfd1036772b8f6
297 745ee8e3e74dc0674dd8018999707f025a9634f5
298 f507baf298549096f08dc33de22f7301e9799814
299 bd7ebd663da867692f2316b94db73c42c0f9a5d1
300 697f07726d209cac519b528018559f8957c56069
301 2297b5172c0c1c83f2d78fc726fac0803be6eeb9
302 91e3543f82039a446c5be8293d5a79ec767d1444
303 e997169214440256b5b759f6e7e255a302838c97
304 77d174ae14afbc6e212eb7d957b11a231a036d96
305 3e81ee29892006f16d5f1f26d9d6b341a8958fb1
306 59957e1d84f8fe8117d9697154c3951ba2959480
307 96c6fa03962edb98a9b6aa7793be4ff54e79bfd5
308 068a293fd6b4fcf216fb84ca982699095613af37
309 b3b1804ffad1b7d274bc3f8f5aa11b15049ac030
310 63e394c13a50de0d9f6cef55a8c91830200c3dac
311 e7ed33eba96d590bbc7179fd26db707c910d1dc5
312 6b2084340a988f4123e71c6e30817806ec4cf3a3
313 da721d3f48f821faa90d1a4778d77b03fd3dcdeb
314 a433cb8d56a4fcd50bfc74b0204c916e08c9d5e6
315 067fae6fd778d5b1d6b6436aedc0d25db58334d1
316 e34c192a5aef80c7e83c78c2372602830671ca5a
317 861a44dc56a983262caebf909be96c62254930cf
318 417ed493a824863e30922deda64b9729b1c6d6e7
319 2df6a0d803ac21f0d20ae9fce0a970b35b3663ec
320 44bedcfc59292d3ff6b36759b324812fcb779b2f
321 c620f7e60c8ce4ddee8fc1072b2a161fee862545
322 82ce5a39b422aec7572d9a773f85be8eaecb1618
323 dc0ea6defad83a0569896a9c23f11f5052a48107
324 e1c15f1da71a3aabdd43a8ad669d2a755f315c77
325 c78ee1aaa5c499019948c9a3dfca3aaa2f897860
326 e66d0d34c541c6588da3ae06c6aff7e7c9ef5745
327 c24d513d46b3db5b4c53b36b7e43ce5fdfd5a2e5
328 a75d0a4bf6d2e1a9c4026586cb707f254691eb3b
329 41e98ebf4526e78d78ab16182b503f237e77fbd7
330 2182dce8c27c33f9452e7c910f59750d1e58b1e3
331 6b7aa9fdbdd0160ec29b6b3b591169c627fd0f01
332 b39470063e41ee5773f47de325a845666d0721ce
333 c7941bdc8822ae1842d2a2f42924f31d2d37e864
334 fad6e836009429e88c788ab7e7a679d422d8cae1
335 a478917ebcf70c5dd6f56c7cd139832108696189
336 4101b1ae3b17e229c1a80d9c302b74d215d98f04
337 b051ec4e69a99e26d6a6e5d7a393014f841eed6a
338 5298ce551a104605b7d5d9872387f3eb704fe5e9
339 b14a12bed26d53eaccd1a2c172ca4a38773e1d45
340 4ae0790397d05a758013e0496ba2c2b23363361f
341 431f01bf3aea6f8baaf06669172561a3ec9e82db
342 12476263aa193c7e921ad4b183fc648bd73d2a1e
343 8e937050fb12a62e99b0cf685578213552774cc4
344 b85a487787454f6dac84be59f905b8c929f0ee94
345 dbb2116e0f03fe6d84d2158d67ddd02761938bda
346 57186ad57242ad0bcd737c4ca4ecb7c063979a95
347 cdb4a295593cb3ad424b4ab86d74154d7bbb97bd
348 8e9e1ae0edb776f0a490005b838f8ef82b368be7
349 73f8f21a69a03cdc2b1031bca214a6b84f4c867c
350 b913c6d878ac5cf570e6f8ba9b5ff022ed601a8b
351 b98879530fd51f328441d33c64c6c5f311097e15
352 325b21b5370a0c179b40fd596b9daea00b3615c3
353 6e722a5c5393dda24172de6f8e08138bcbfb10b8
354 44b396caab82c97a6270eb7391d6f96502c9fcf9
355 4e6ed6d22079b68551bbb83e5dd797517796a438
356 b611fe79daa20893683475cc459dff98b2d4892b
357 017d40f9b23f4a4379c74ceeb89ce7b4bccb7460
358 a31b0a7fc7190218136d6ff6ffb3ee6af3244135
359 861bd42abb90a61ed757728e1fef7cee2d6aa081
360 6e9ff586de744d166a9f6f213b609e7386692472
361 a790ca7384982e872092766c036d6faa86bff71a
362 13485c50ca4dfd885d516154421bdb23cb034230
363 c5471e696f3166942a245e77796bcddafe6a607c
364 600308daf62d0d651fcfc874110e7bd4f5de648a
365 bada607744ec7f37ba9d05c09bb8f41e7fc3d06a
366 d3b230b209fd7c3f4a39db965b239ab600fac1fe
367 6d730b7ae0b662b1f987101e8ccf9c1828554d69
368 f0757668fcd3f8d1f2fe83ce9f0e2355b6be75f9
369 40819d9a5631a184a17d38e36240d1171a6fc923
370 8a6847ca68ec998df0543c4b5bd5c709c05d5f12
371 d8eb0646ae1360b5b984ba7d99bc64e00dd67016
372 761bf1cc1e2b86437e71c9a106fc9c341097c3bd
373 3b620d960d29fa7719f95cf945163b04e43d2dad
374 6be8590f72c2ef158202486e75f273d8598be6bc
375 d7f22a15d66139efd65bae28ba780b0bf8d1a914
376 e1ebbf612cf9d49cb08d0e0770ac1678ce1436ab
377 4db9912f07ce63e4519053f52dbe521ec95c0fba
378 b9fd4f4760ef65934b5d38e8b7c0eb2f77822861
379 0e0178ecfacd553526afd221734607971b6911f1
380 8cd4823a8ac9f846930408ad1759da4496384f9d
381 e96cf22a972cc3185739ef1c1ce74a978ab71d11
382 a9d63829aa54049801d37429b597eb04c9e1412d
383 2519d617e18fa35974e20d10414f1262013501bb
384 d02fc8d8483903871d9f65261b32c6acd2e4362d
385 569456505d5c97934344d4f989a08fdcdb522de9
386 f56d4c60ffb8df8fc1516d32a0512def0b6f8296
387 745e899452ec746d3ffbb7b082995b7939a85387
388 8c11f9ca2433bf9381840696218c245ec700666c
389 bc2a868d1ba12b485a6eac460cefee67bd9ee899
390 e628b072d054d982ecbbd7aa7fec628e0d9ee8d6
391 e3390afd65e721dd8ef228f48fd4244228de2986
392 35102507bd653296eaaa5e7d475405cc1feafbe3
393 e2e5342f92148238391665fba101b1ca7dad5582
394 621f4743f0165c6ca3f1571773867d2e0da67961
395 5f558819695a49bbb92d5d1e07b9f12072874024
396 eb45e9da84875e2d1325b78157d2f9e96374bdae
397 bc0ab7e4f643e779cf9554f03e567d4f4708bd4d
398 fd55e896d6df035cba49a20e26ed6ddd2d7b6024
399 dcb9d95840c9a0514f8fd0a7b3b17cc228950c7e
400 0bedc3d7a01f9819171c0b664e16900d9965c3ae
401 94f6e372fd90e96cfd9a393a5952aa850485de66
402 0b889a9cf37997c58a9f8979850da1f4bc84de9b
403 b70ec5facdea7fc681c2a10dfb14ca0d8fed6f1d
404 03e0192fb34134f25784a2b14791fbfdf69461bf
405 9266cc52df3725107edf513aea4a02c131aa153c
406 0820a412fdc9941567d86cba02793ca6a6378275
407 f1a72254956f63393f6039a7d5da5fca943fcd2c
408 abeb9e16d924c1a87c5b525ed12c43031ef1cb2f
409 d5813fad322c97bc31d7dd37f838c7442aa68f35
410 428b26fdca0ba98a3a01e89629bdb778dec9e8ab
411 19ff672db65a7ee25ee0d48baa3f9bbf2d145ecd
412 d1eb6283ece7d9c814b0d3d5223207b905d3d720
413 9ba934b83a40d26ebc5e8d7304ff29c32541e82d
414 9b600cbf0209ad6079d00dd5d6a5270d858d5929
415 0f22868d790bfab8a41894fc7eca161256ab6854
416 fba092070b6e03432f6d47154f5ae4734e935a05
417 11b1bf011fc24c2ca6dd8c81206c7338ac2b2915
418 d93c82b17d7416e4c57ed036d6b75a323859d837
419 27f762e8d3f1ed8bd0254800c121d0f16e914c2e
420 e252d9d270330072e9e5e91257e90f255e7e968d
421 e55c3c30785eb50b5dc36f9568e6b6ae39e6de11
422 63491807090d814bd7ffccfe44cb05795830eb3b
423 8111dbaeb71c53132229c4064c34247746a3769e
424 8fe37ca0d79dd1f8132e9add06aa206d371964e3
425 eb32fae4665b9f11ffd06a342e763b9d212e1353
426 4e923698ee5566143fc6d32fdcc6fb46fcda2d23
427 2e3910e29142382f9bbd1705ab9c605d1937a1ae
428 533cc5f884885f771d3f6df4164fbfa29bae0e6d
429 3fea0404fc58822cfc60d4f10ca404e3223f82a4
430 733404a081eda804707c3dde1d6b8161e7a34b3d
431 d2be0ea2923344abed57aa21f13dc816d4537eda
432 7884465bb9da51c8b6e95a1cbc9888ed696ff68d
433 6e63e5a03bfbba52dc3b4f504e6bc41951f56707
434 44a9d3ed75c44e817a6e4b56e30be06a15f453c9
435 91e12aff0f988bf414e64b97a8c20b9699440309
436 008119e510f6a7f8714e63d2ec33ca7cd7776ea2
437 27822b01ad020374ff6169428649fd667abf7f8b
438 0c972fb8903c656cb7e750b1d5c1ea1f26bd8c50
439 3d8f3e1fae697a905e87250aa5c0ae1f6c60ad66
440 744421b6f1d3aa30c7558570da8aa1d52f11d39d
441 ac017796cd3a5558dd78f73ecb82a6b961d8a3ec
442 e11f534a2fd666ecd841f657faf0751d5fe02034
443 eca5d275376911916c3e018c2d163cb8eb914263
444 a3144ddce360b6ac1b55fc27d19a318be1f224c4
445 84fc7d68bf3a309b3687da768f0dc206e647e653
446 fd5132bf8e99230a9074ce9bb3d950cd26b3d25b
447 720ceb5e566d26803db85af3ef69fc4fa14d355e
448 e97f338a79e2248afd3a2b9077d8ac1c334cdf38
449 0173ccf8d04014bcc4cc53df4d6574540f4231e4
450 52da09b8812d96c14d3e57a77784d56e5749a8ae
451 5169648c7429788c777947e21527e121d35aebe9
452 41c8c94cdd1c646296946a00dc72dff8fcb6556f
453 9b341f77b72b55674a030ad0209ac297e41c5570
454 6aacd7b9b8fc571e930d18da63efc8be46e31bdc
455 9875e5d15c0750b6ee4c41b0e1321e1dc0bb7810
456 fd60909d92b0e124957aa0783ea03471c73fd732
457 2f299011d707ffd8502e5a597f38f0d25ab3099b
458 6c10423816abd3b0f327863c9b8fcf55cd6265bf
459 14cc60568455ac2210f00ccb238ae41ddb473fcb
460 74cf0e9a42bf241d3f76f25aaed46e4b6550d842
461 9a0eacdab0398ced7d729f5c7a9b173eada2dcaf
462 3057f2e5ac8cd11cd018780c062da7c2bb11d2f7
463 dab224a6b259d9d7e16af4cf7e2718af8ba4a74c
464 fe6dc165cde8c826a3935b536c8cfd1c10ba7d62
465 7f3572bca7fd48b66649d761a054412b8369deba
466 2ea30dde468795a3ccb307343cd50eb7041f5ee3
467 5d4099ededa31d823a355d4ef0e53bed6b833539
468 69eb5257143b2de63c8c7471216ba6f025b6d7ef
469 e4c7387b32e314cca7e0ee2b1df197340272fad1
470 01f14dd38700098d97f933008327c8456c75af34
471 94040e25d5aacae0e55c3e9a91fe24d7daaaaaca
472 cd64f093886bf092b8d88c75ccd2e2f9118d3ba9
473 ceb96f9512f80188fafc61ec8d8d61c93d51a5c2
474 9a4e9bf98bd371cee2b69ef62a1189c24cd8baa4
475 dd861f56b65404a625538978d50819924f384a60
476 b2960c129e39d30f446d27e38f726975bef7b4f0
477 8351c6b1293bb0cc4a2e1235995c16433c84c463
478 008ba61116504d01558fe8afea0d5b3e90944b76
479 cce20d2824a877ffed6a912e3f22d7db3d8e5043
480 5e02e12edf58e1dfe37ed770fb32171e64993a81
481 7966a56b3a3c9c9ac6db5b9355ba5e96558ea7b6
482 5dea2f86730665894cf03f2b1fac98c1217a9fb4
483 451a4d8118d2c9c746c687efceaacac799e67ad9
484 059dfb5adcde569a19a9260c2ff85c7b47f8c516
485 da7449db2898c567fcfb40c595c0c21536c901b8
486 db97ce996b09b15049a9f818ce27a680e585bd11
487 e1f95b9a8fe2394e1cfb41fe83f130bdb68fe6b4
488 fc2c03e29a331cafc8b08abd5eade336904f40dc
489 385b11a95469f7477bdcf5b9c743982c4a866c65
490 d7e31d19b9ed766048ccf9129723ebe36b4842dc
491 9c9af56fb29f510ef75221a39964c128448526bd
492 83e3c642af5648aaaa119cce34dfef6ef3c560bc
493 a831fc506ca30a11c9d9b33c9cb2c43f6f01a446
494 62c5ebf183a0cc2332f04c1ee3323005a9878438
495 6bb31edda343bbbc4410e2f780c432129e610b47
496 846ef94e8af8f09340a740d11c93157c81079bc0
497 47aec581139d8a3ab4f2969b481868c1485e2ac6
498 e3f68d2cd84e15063c4f73c8420a444f9fb64a7a
499 3db1240470361a7314ea096f63c0fde74810caba
500 ae951371c666cc605ef69b5ca3f5f31d0cd30298
501 8ec035e739f01aeaa09742a92154f02ab3dbfe93
502 4737a65f7c1e125ba37ef35acbc6e99c4db2bed6
503 7005d4cae81a16a5a860fcd3c259d6ec07597072
504 d98807cb107ad2e9bf95138ee4bfb566bf75cb50
505 1e8cbd548f12e1ec861f3aed5fa9f080cf2782c4
506 25c2b2cad9cf873edc80747cd2df5874034282aa
507 676749cf8f76eadb469289b1d918cb5e485cd56b
508 8cba76ab8a5034ee21e95a99196f257b7e527b49
509 0151aa85f5a178da21ddf7d5e81398fff87604dc
510 f881500552171b5a8a8c3ec7a2dc06e493a1ebbe
511 8d39edf2ae13ed33d0529164d4e172bd4d060d7a
512 b5c3f29c81e524e860e5f9ebefdc573f83fc600d
513 b686bc7a882e461987ffb7bf1a25bdc6f82ccdd3
514 ebc1f42a059e7863adb57890562878f652922b56
515 b30835cea58d0b827cb56aaf9e4d5f6e673a1bf1
516 a2cf1028df49cbf53c57d0f599083fec59cc38b7
517 6efa045dbdfb4272f075255411f54fe436c31b8a
518 0c3f085a4044e9231287c11e34504624b04ee7cf
519 b8e628fdc2a7627283e0601ebfe8e978e91dfc00
520 d84e30103d59d6bace53223fc0d5787f03d7f028
521 2e0e70d0466bde79d134a215a399b20c2a9d0981
522 142de640101e2bee71fe2dc98e567d688c7e3aa7
523 8b02a5e91092f7363443a1cf96933dc445f0ce51
524 753c065260b1659c0d8d247b62f6b0fbe986c7b2
525 1113b6978475c9941be9b140e8cd6bc267469657
526 0a01d10b21c039484410c7898250afc4079db28d
527 b9bd23fa584a8f1900ada4addb96eeb750ef0a68
528 5ecc9b675c4cc5c1bdcd8f84e1a52457ad30144d
529 d91b0a31122b251998915b4eb274350fd42a841e
530 a829cb9c850cc75546547aa95fa3ca6100ce16f7
531 4b9bba5d1063d986be6463e4c5740eb18befc7b6
532 ffb2f17926143e242efc18b32ee0c630b5447687
533 3feb18fbff52f17a541abb1ebbb4894beec18d55
534 4acbde9bdb24bd802ba5bb0ebe19d71c8d753240
535 c9dba689c67ad7b16c8f6b1bf1bd382369fdec4e
536 ff956cafd71e4787e9ef7b64725142fe8838a65a
537 e2c090f1ca171b51d08e6ecbb74b27410bdfa7eb
538 73aa4812a2effb88bb64a42f93713a54a88e1ccb
539 8e0e0c69b0adb9a65098b18a7b96d6ed3a43940a
540 5dc8620cb17c3e606b635f8f95ecebdd66af04ee
541 18f8afd6fc87b3731145f61818f23b4b766da703
542 0d2d0bd0680557dc28f4f7b23562495cdbb3afc0
543 94da53667213590ad9767b335a9f2e51fe1e2c5d
544 c6cb97a42dcea5461a2931b097ddfd53b9cc5870
545 62a3d5192232ed847f3c7810344c43607a361e68
546 aa6992567e763a0b081e6bce753cc42bc287e9d3
547 1d67358d33250d456040091d8b29083b1b47d9bb
548 65d399a4ac7dc36df20b8b2bc773bbc6fa67f43b
549 acf7ea014fd1b7eb351dc6946b199ad2cc98f845
550 7e4dcbb7f0fc2b051e33b555c4fdc67796dbbab9
551 a07916245a9c21f3874a7b8c898638ca3b65df42
552 bb7368d9b07b02aecfbca6d01788a7327743ffed
553 60454c29275aac27c450323f0141d60ea8202842
554 c4d0ff10c85ca4c12ddfda1830cee475408205d5
555 a5da3671524fb761552a4eb5c1e27dd433f80fe4
556 43142e711f392ae1bcdade749dbaa9dd98664228
557 7aa0bdd118c78d8929e737392457d14f87d625ae
558 be921331245c4e04ef9f0ff7e359907e2d101cac
559 d6f654de1b8c27f84e34fbff12aadffb30342465
560 fef2680b335ffd861021ceff2a2637f5a360f037
561 79de53d3b87469e21d510ed6ddb33d809c05a3f6
562 475b10017d25db725e73eef11ca789ad7dfcf4ac
563 d14f3734dc27ecccfdb4683cf7ef3334a5a70b3f
564 f0c394dd6a109b97ba4a9ab16cc71b789d9ee38b
565 a57cd5c8278e1fd6fae6f02947c13880be4f3b62
566 83c6e4b636f3bf115955b6eeb3f91a5689e7f00b
567 b881752a8cc16f49ca605bf6a35af106e7e19c9a
568 8362e4bcc30e73460ae1b9731bc545fd2b12d8f0
569 b01216229149bed7c110221551353b54ff8e4704
570 10ad0e68785b27bab975868b83bc463b9c9c9153
571 7a66612abaa223ef0410fae66727a8abac3add03
572 8a7bdba957536b078f0421faf5dfaf8d65ff5add
573 defd6d03526345a410437eda15cbd067124f9c2c
574 f7e6c29aa4d1f7a607e0c87ea20105afeee0372a
575 751363e461257a4036a8f2aa740195401883c1ea
576 a8d66b5855eda5abf699ebf9c6dd721928007fb8
577 35ca716114bdf87a89857f2d633be3f4b13cbc70
578 cf319abfba8fc1b33de4c6a6f99e21864cc72563
579 4fd36e634e762ff2f94e9d66f24ceabe164f9e26
580 d0364113a1b57ed5017dbea6126b0cc5a5c2886d
581 9b3d7bf551d20acae4ee943a86c3cf898b6280ba
582 b35351d566efdde005747503c7f121d49e864848
583 57b1dc2b20f2e67c3313f0c6127b05041d125fb4
584 fadcdf4c98e9167f8f06a45dafa08d3acce7a741
585 3bcfcb7717bfc0e50c5b8f5c7beaed9f3ddf5478
586 b8388b7b5973dd3e84902c25c5378f9a412d6147
587 814f07ea363eb0464380ccfce7b4cf5209f1dcb2
588 b33315c8551bede3fb867efb3fdb1134cdff5115
589 c7bade1e7cc239e8fceb2c0b06f880e60eb8ebec
590 bb193f4f0f5b1b8bdc9cc72967f8fa6387faf7c4
591 b727e8d9f4a4987cbad41c75c630cfdb445c37a0
592 a2103d7fe328871d8231f8e07ba5dc9182f637b3
593 e36d269d16660db5bba028746564b5699721def5
594 35f9c486cc26bdff903241f4ab2b1dac2536059f
595 cd5314af7e8e120bceda896a3c17daa8eeedd528
596 200e09df8f0f7b94eb8941136482cf7c60fffb0d
597 17a618f241a6236c93af5ba2e09238369fc7d784
598 15aeb2bb0401d428cb7058e1d6554e20369ed352
599 40b0a406cc23467af8bb63d9a62378fa871e2031
600 7abd7f4cb237ef33b9e019f4529b6fb05b84284f
601 ac614b7506e820457417c3ea15ba99fbc8146155
602 8afd5a714da3f45389e0e4edeb64f49576c57c76
603 77d10571047d8b4153180e7a89d5c9aae6a84060
604 35479ce1706725f73bfe99428c43e8fe2e3f9157
605 360a0864ece712571d3df95e86251d6883bcdf7d
606 b5cd910848f592e33efb6de3226c07ae545a2aad
607 f5a9c28ca029ec5d1c5d3c594afa09374adf04e5
608 b9fce5928a1c5056f66706b67c01cd564e6c0a90
609 e5a2250e35706127304cd5ed86b81575f2636b5b
610 f30cffe4cef93aa190bcb1caf407ca0767107d06
611 45535f6e0af6785676531c81b4a2a3c480a98e70
612 740bd201b23beded9ade92a93301cddc67c4d106
613 70460e9e601171276dd6844cd6addd8db5eb2465
614 44dff2c35acb4736b183cef9e46155386f579716
615 46ea31f673bc9365fcca558f15c862ef6a899018
616 34556caf76c2422a76be3d1cecd223fcf435d93c
617 fea67ed9483b5cc76dc55eb4dd6f52baf445394d
618 31b1897ece6222826f379c1aebda891384b4b63a
619 80dcf3713b85b78979d4eb443fce9e992675b5c0
620 11993c742658321c0c5c200f48231583216d636c
621 7b5a089ed3007252e61df0aee3fc17c14d051745
622 890881c9a552c22f4be01dee16ee902c88f6700f
623 401ba79da09dded82a73996c8e0609a87cbd728b
624 e06313f41971de730085dcddf640a4549fc54fc3
625 054d52e86a954a615ed1f5add7f9d6842737d965
626 d8a60982c456a9cae3de745a37dc3f5985814f7f
627 2b39f575a510cf581aa828df494e633cc76fafa6
628 e11d353191175b329b3c9f9af7fa33e3ef9f837d
629 32ac2659ce98765aaae9c10cc7216d1f1faf155e
630 5f7f801227868c7abcce7e58dee3eff855011955
631 a013eaf0fe38d8689e27278bddd4ebf87ac5476b
632 401b3f3d2d96fa785c5321bb64c97cfb17c509e3
633 1fa4fd4321fa708b3db5cfb514e2192b00672aff
634 77976b24ff839c59c3b20d80cb28351ccb5e59a8
635 09b76d2966e2370a78ed37a31c2f7c23d08609c3
636 7000b24511618a21d40b39ee213d397e1d29497d
637 c2a6adfcd18c0d95dbed6ea62ac9c9a912d18123
638 6ba3609953d5c46a76ca1d0d3d83018be61454e6
639 3dff6074fe205e36fae219f277ef87aab097e236
640 1cdc8437fa6c621d96c4dfa5f6370c8fdb9cbc3d
641 d471720bc8f7ce7109276b49dd9c76b6163007d9
642 a67b1bdd027629dfc38601b21dc564272e28712c
643 20125a6d37d5c1614ffe1de94ca064095968e7f0
644 2b642751ef86265a1c953186810e118740f8bd2d
645 e562c1d74e2b6744572184e66a0673e55f9ba0b8
646 ba9687b5d746dda28d4a19c5c96d0679d7c77b15
647 f39d7d293c3e342b4f447bb440a9b6f72d2d20cc
648 95750ad9e700efd15d137963ba0dc443e6c9b6b0
649 0f76d8445048dc0bfcaf05e30b61b338a08f0e48
650 1a9a4c61d6a371d9e95eaef44fa2452d17a09d22
651 912b41aad5983d9735379d322eae8f6d40d8bdca
652 eea0b559472874ff48c34f16bb805108967e6489
653 ad4e7ba4032e6b1c047230b3144848dbcf66a127
654 b6d93107393dee6eebb05376a67f2e4dfcb44311
+0
-8
git/test/fixtures/rev_list_delta_a less more
0 e34590b7a2d186b3bb9a1170d02d52b36c791c78
1 8977833d74f8681aa0d9a5e84b0dd3d81519774d
2 6f5561530cb3a94e4c86454e84732197325be172
3 ee419e04a961543444be6db66aef52e6e37936d6
4 d845de9d438e1a249a0c2fcb778e8ea3b7e06cef
5 0bba4a6c10060405a94d52533af2f9bdacd4f29c
6 77711c0722964ead965e0ba2ee9ed4a03cb3d292
7 501d23cac6dd911511f15d091ee031a15b90ebde
+0
-11
git/test/fixtures/rev_list_delta_b less more
0 4c8124ffcf4039d292442eeccabdeca5af5c5017
1 634396b2f541a9f2d58b00be1a07f0c358b999b3
2 ab25fd8483882c3bda8a458ad2965d2248654335
3 e34590b7a2d186b3bb9a1170d02d52b36c791c78
4 8977833d74f8681aa0d9a5e84b0dd3d81519774d
5 6f5561530cb3a94e4c86454e84732197325be172
6 ee419e04a961543444be6db66aef52e6e37936d6
7 d845de9d438e1a249a0c2fcb778e8ea3b7e06cef
8 0bba4a6c10060405a94d52533af2f9bdacd4f29c
9 77711c0722964ead965e0ba2ee9ed4a03cb3d292
10 501d23cac6dd911511f15d091ee031a15b90ebde
+0
-7
git/test/fixtures/rev_list_single less more
0 commit 4c8124ffcf4039d292442eeccabdeca5af5c5017
1 tree 672eca9b7f9e09c22dcb128c283e8c3c8d7697a4
2 parent 634396b2f541a9f2d58b00be1a07f0c358b999b3
3 author Tom Preston-Werner <tom@mojombo.com> 1191999972 -0700
4 committer Tom Preston-Werner <tom@mojombo.com> 1191999972 -0700
5
6 implement Grit#heads
+0
-1
git/test/fixtures/rev_parse less more
0 80f136f
+0
-6
git/test/fixtures/show_empty_commit less more
0 commit 1e3824339762bd48316fe87bfafc853732d43264
1 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904
2 author Tom Preston-Werner <tom@mojombo.com> 1157392833 +0000
3 committer Tom Preston-Werner <tom@mojombo.com> 1157392833 +0000
4
5 initial directory structure
+0
-6
git/test/fixtures/uncommon_branch_prefix_FETCH_HEAD less more
0 c2e3c20affa3e2b61a05fdc9ee3061dd416d915e 'refs/pull/1/head' of http://github.com/loic-bot/testrepo
1 fd8695d980e2c6df62b7785f93fd6292d1e283fb 'refs/pull/1/merge' of http://github.com/loic-bot/testrepo
2 bb46faf089720d1a3f9e4dc3b11ed5ff77d7e764 'refs/pull/2/head' of http://github.com/loic-bot/testrepo
3 5faa366d58454eceea811e0e34c502bdd7b37e4b 'refs/pull/2/merge' of http://github.com/loic-bot/testrepo
4 b3ad3c4f1864b50d4d3e09320947a1a3c34c9ea2 'refs/pull/3/head' of http://github.com/loic-bot/testrepo
5 71fe57e511776042b009ed4bb281b62b0522b434 'refs/pull/3/merge' of http://github.com/loic-bot/testrepo
+0
-6
git/test/fixtures/uncommon_branch_prefix_stderr less more
0 = [up to date] refs/pull/1/head -> pull/1/head
1 = [up to date] refs/pull/1/merge -> pull/1/merge
2 = [up to date] refs/pull/2/head -> pull/2/head
3 = [up to date] refs/pull/2/merge -> pull/2/merge
4 = [up to date] refs/pull/3/head -> pull/3/head
5 = [up to date] refs/pull/3/merge -> pull/3/merge
+0
-12
git/test/lib/__init__.py less more
0 # __init__.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5
6 # flake8: noqa
7 import inspect
8 from .helper import *
9
10 __all__ = [name for name, obj in locals().items()
11 if not (name.startswith('_') or inspect.ismodule(obj))]
+0
-375
git/test/lib/helper.py less more
0 # helper.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5 from __future__ import print_function
6
7 import contextlib
8 from functools import wraps
9 import gc
10 import io
11 import logging
12 import os
13 import tempfile
14 import textwrap
15 import time
16 import unittest
17
18 from git.compat import is_win
19 from git.util import rmtree, cwd
20 import gitdb
21
22 import os.path as osp
23
24
25 TestCase = unittest.TestCase
26 SkipTest = unittest.SkipTest
27 skipIf = unittest.skipIf
28
29 ospd = osp.dirname
30
31 GIT_REPO = os.environ.get("GIT_PYTHON_TEST_GIT_REPO_BASE", ospd(ospd(ospd(ospd(__file__)))))
32 GIT_DAEMON_PORT = os.environ.get("GIT_PYTHON_TEST_GIT_DAEMON_PORT", "19418")
33
34 __all__ = (
35 'fixture_path', 'fixture', 'StringProcessAdapter',
36 'with_rw_directory', 'with_rw_repo', 'with_rw_and_rw_remote_repo',
37 'TestBase', 'TestCase',
38 'SkipTest', 'skipIf',
39 'GIT_REPO', 'GIT_DAEMON_PORT'
40 )
41
42 log = logging.getLogger(__name__)
43
44 #{ Routines
45
46
47 def fixture_path(name):
48 return osp.join(ospd(ospd(__file__)), 'fixtures', name)
49
50
51 def fixture(name):
52 with open(fixture_path(name), 'rb') as fd:
53 return fd.read()
54
55 #} END routines
56
57 #{ Adapters
58
59
60 class StringProcessAdapter(object):
61
62 """Allows to use strings as Process object as returned by SubProcess.Popen.
63 Its tailored to work with the test system only"""
64
65 def __init__(self, input_string):
66 self.stdout = io.BytesIO(input_string)
67 self.stderr = io.BytesIO()
68
69 def wait(self):
70 return 0
71
72 poll = wait
73
74 #} END adapters
75
76 #{ Decorators
77
78
79 def with_rw_directory(func):
80 """Create a temporary directory which can be written to, remove it if the
81 test succeeds, but leave it otherwise to aid additional debugging"""
82
83 @wraps(func)
84 def wrapper(self):
85 path = tempfile.mktemp(prefix=func.__name__)
86 os.mkdir(path)
87 keep = False
88 try:
89 try:
90 return func(self, path)
91 except Exception:
92 log.info("Test %s.%s failed, output is at %r\n",
93 type(self).__name__, func.__name__, path)
94 keep = True
95 raise
96 finally:
97 # Need to collect here to be sure all handles have been closed. It appears
98 # a windows-only issue. In fact things should be deleted, as well as
99 # memory maps closed, once objects go out of scope. For some reason
100 # though this is not the case here unless we collect explicitly.
101 gc.collect()
102 if not keep:
103 rmtree(path)
104
105 return wrapper
106
107
108 def with_rw_repo(working_tree_ref, bare=False):
109 """
110 Same as with_bare_repo, but clones the rorepo as non-bare repository, checking
111 out the working tree at the given working_tree_ref.
112
113 This repository type is more costly due to the working copy checkout.
114
115 To make working with relative paths easier, the cwd will be set to the working
116 dir of the repository.
117 """
118 assert isinstance(working_tree_ref, str), "Decorator requires ref name for working tree checkout"
119
120 def argument_passer(func):
121 @wraps(func)
122 def repo_creator(self):
123 prefix = 'non_'
124 if bare:
125 prefix = ''
126 # END handle prefix
127 repo_dir = tempfile.mktemp(prefix="%sbare_%s" % (prefix, func.__name__))
128 rw_repo = self.rorepo.clone(repo_dir, shared=True, bare=bare, n=True)
129
130 rw_repo.head.commit = rw_repo.commit(working_tree_ref)
131 if not bare:
132 rw_repo.head.reference.checkout()
133 # END handle checkout
134
135 prev_cwd = os.getcwd()
136 os.chdir(rw_repo.working_dir)
137 try:
138 try:
139 return func(self, rw_repo)
140 except: # noqa E722
141 log.info("Keeping repo after failure: %s", repo_dir)
142 repo_dir = None
143 raise
144 finally:
145 os.chdir(prev_cwd)
146 rw_repo.git.clear_cache()
147 rw_repo = None
148 if repo_dir is not None:
149 gc.collect()
150 gitdb.util.mman.collect()
151 gc.collect()
152 rmtree(repo_dir)
153 # END rm test repo if possible
154 # END cleanup
155 # END rw repo creator
156 return repo_creator
157 # END argument passer
158 return argument_passer
159
160
161 @contextlib.contextmanager
162 def git_daemon_launched(base_path, ip, port):
163 from git import Git # Avoid circular deps.
164
165 gd = None
166 try:
167 if is_win:
168 ## On MINGW-git, daemon exists in .\Git\mingw64\libexec\git-core\,
169 # but if invoked as 'git daemon', it detaches from parent `git` cmd,
170 # and then CANNOT DIE!
171 # So, invoke it as a single command.
172 ## Cygwin-git has no daemon. But it can use MINGW's.
173 #
174 daemon_cmd = ['git-daemon',
175 '--enable=receive-pack',
176 '--listen=%s' % ip,
177 '--port=%s' % port,
178 '--base-path=%s' % base_path,
179 base_path]
180 gd = Git().execute(daemon_cmd, as_process=True)
181 else:
182 gd = Git().daemon(base_path,
183 enable='receive-pack',
184 listen=ip,
185 port=port,
186 base_path=base_path,
187 as_process=True)
188 # yes, I know ... fortunately, this is always going to work if sleep time is just large enough
189 time.sleep(0.5 * (1 + is_win))
190 except Exception as ex:
191 msg = textwrap.dedent("""
192 Launching git-daemon failed due to: %s
193 Probably test will fail subsequently.
194
195 BUT you may start *git-daemon* manually with this command:"
196 git daemon --enable=receive-pack --listen=%s --port=%s --base-path=%s %s
197 You may also run the daemon on a different port by passing --port=<port>"
198 and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to <port>
199 """)
200 if is_win:
201 msg += textwrap.dedent(r"""
202
203 On Windows,
204 the `git-daemon.exe` must be in PATH.
205 For MINGW, look into .\Git\mingw64\libexec\git-core\), but problems with paths might appear.
206 CYGWIN has no daemon, but if one exists, it gets along fine (but has also paths problems).""")
207 log.warning(msg, ex, ip, port, base_path, base_path, exc_info=1)
208
209 yield # OK, assume daemon started manually.
210
211 else:
212 yield # Yield outside try, to avoid catching
213 finally:
214 if gd:
215 try:
216 log.debug("Killing git-daemon...")
217 gd.proc.kill()
218 except Exception as ex:
219 ## Either it has died (and we're here), or it won't die, again here...
220 log.debug("Hidden error while Killing git-daemon: %s", ex, exc_info=1)
221
222
223 def with_rw_and_rw_remote_repo(working_tree_ref):
224 """
225 Same as with_rw_repo, but also provides a writable remote repository from which the
226 rw_repo has been forked as well as a handle for a git-daemon that may be started to
227 run the remote_repo.
228 The remote repository was cloned as bare repository from the ro repo, whereas
229 the rw repo has a working tree and was cloned from the remote repository.
230
231 remote_repo has two remotes: origin and daemon_origin. One uses a local url,
232 the other uses a server url. The daemon setup must be done on system level
233 and should be an inetd service that serves tempdir.gettempdir() and all
234 directories in it.
235
236 The following sketch demonstrates this::
237 rorepo ---<bare clone>---> rw_remote_repo ---<clone>---> rw_repo
238
239 The test case needs to support the following signature::
240 def case(self, rw_repo, rw_daemon_repo)
241
242 This setup allows you to test push and pull scenarios and hooks nicely.
243
244 See working dir info in with_rw_repo
245 :note: We attempt to launch our own invocation of git-daemon, which will be shutdown at the end of the test.
246 """
247 from git import Git, Remote # To avoid circular deps.
248
249 assert isinstance(working_tree_ref, str), "Decorator requires ref name for working tree checkout"
250
251 def argument_passer(func):
252
253 @wraps(func)
254 def remote_repo_creator(self):
255 rw_daemon_repo_dir = tempfile.mktemp(prefix="daemon_repo-%s-" % func.__name__)
256 rw_repo_dir = tempfile.mktemp(prefix="daemon_cloned_repo-%s-" % func.__name__)
257
258 rw_daemon_repo = self.rorepo.clone(rw_daemon_repo_dir, shared=True, bare=True)
259 # recursive alternates info ?
260 rw_repo = rw_daemon_repo.clone(rw_repo_dir, shared=True, bare=False, n=True)
261 try:
262 rw_repo.head.commit = working_tree_ref
263 rw_repo.head.reference.checkout()
264
265 # prepare for git-daemon
266 rw_daemon_repo.daemon_export = True
267
268 # this thing is just annoying !
269 with rw_daemon_repo.config_writer() as crw:
270 section = "daemon"
271 try:
272 crw.add_section(section)
273 except Exception:
274 pass
275 crw.set(section, "receivepack", True)
276
277 # Initialize the remote - first do it as local remote and pull, then
278 # we change the url to point to the daemon.
279 d_remote = Remote.create(rw_repo, "daemon_origin", rw_daemon_repo_dir)
280 d_remote.fetch()
281
282 base_daemon_path, rel_repo_dir = osp.split(rw_daemon_repo_dir)
283
284 remote_repo_url = Git.polish_url("git://localhost:%s/%s" % (GIT_DAEMON_PORT, rel_repo_dir))
285 with d_remote.config_writer as cw:
286 cw.set('url', remote_repo_url)
287
288 with git_daemon_launched(Git.polish_url(base_daemon_path, is_cygwin=False), # No daemon in Cygwin.
289 '127.0.0.1',
290 GIT_DAEMON_PORT):
291 # Try listing remotes, to diagnose whether the daemon is up.
292 rw_repo.git.ls_remote(d_remote)
293
294 with cwd(rw_repo.working_dir):
295 try:
296 return func(self, rw_repo, rw_daemon_repo)
297 except: # noqa E722
298 log.info("Keeping repos after failure: \n rw_repo_dir: %s \n rw_daemon_repo_dir: %s",
299 rw_repo_dir, rw_daemon_repo_dir)
300 rw_repo_dir = rw_daemon_repo_dir = None
301 raise
302
303 finally:
304 rw_repo.git.clear_cache()
305 rw_daemon_repo.git.clear_cache()
306 del rw_repo
307 del rw_daemon_repo
308 gc.collect()
309 gitdb.util.mman.collect()
310 gc.collect()
311 if rw_repo_dir:
312 rmtree(rw_repo_dir)
313 if rw_daemon_repo_dir:
314 rmtree(rw_daemon_repo_dir)
315 # END cleanup
316 # END bare repo creator
317 return remote_repo_creator
318 # END remote repo creator
319 # END argument parser
320
321 return argument_passer
322
323 #} END decorators
324
325
326 class TestBase(TestCase):
327
328 """
329 Base Class providing default functionality to all tests such as:
330
331 - Utility functions provided by the TestCase base of the unittest method such as::
332 self.fail("todo")
333 self.assertRaises(...)
334
335 - Class level repository which is considered read-only as it is shared among
336 all test cases in your type.
337 Access it using::
338 self.rorepo # 'ro' stands for read-only
339
340 The rorepo is in fact your current project's git repo. If you refer to specific
341 shas for your objects, be sure you choose some that are part of the immutable portion
342 of the project history ( to assure tests don't fail for others ).
343 """
344
345 def _small_repo_url(self):
346 """:return" a path to a small, clonable repository"""
347 from git.cmd import Git
348 return Git.polish_url(osp.join(self.rorepo.working_tree_dir, 'git/ext/gitdb/gitdb/ext/smmap'))
349
350 @classmethod
351 def setUpClass(cls):
352 """
353 Dynamically add a read-only repository to our actual type. This way
354 each test type has its own repository
355 """
356 from git import Repo
357 gc.collect()
358 cls.rorepo = Repo(GIT_REPO)
359
360 @classmethod
361 def tearDownClass(cls):
362 cls.rorepo.git.clear_cache()
363 cls.rorepo.git = None
364
365 def _make_file(self, rela_path, data, repo=None):
366 """
367 Create a file at the given path relative to our repository, filled
368 with the given data. Returns absolute path to created file.
369 """
370 repo = repo or self.rorepo
371 abs_path = osp.join(repo.working_tree_dir, rela_path)
372 with open(abs_path, "w") as fp:
373 fp.write(data)
374 return abs_path
+0
-0
git/test/performance/__init__.py less more
(Empty file)
+0
-94
git/test/performance/lib.py less more
0 """Contains library functions"""
1 import logging
2 import os
3 import tempfile
4
5 from git import (
6 Repo
7 )
8 from git.db import (
9 GitCmdObjectDB,
10 GitDB
11 )
12 from git.test.lib import (
13 TestBase
14 )
15 from git.util import rmtree
16 import os.path as osp
17
18 #{ Invariants
19
20 k_env_git_repo = "GIT_PYTHON_TEST_GIT_REPO_BASE"
21
22 #} END invariants
23
24
25 #{ Base Classes
26
27 class TestBigRepoR(TestBase):
28
29 """TestCase providing access to readonly 'big' repositories using the following
30 member variables:
31
32 * gitrorepo
33
34 * Read-Only git repository - actually the repo of git itself
35
36 * puregitrorepo
37
38 * As gitrepo, but uses pure python implementation
39 """
40
41 #{ Invariants
42 #} END invariants
43
44 def setUp(self):
45 try:
46 super(TestBigRepoR, self).setUp()
47 except AttributeError:
48 pass
49
50 repo_path = os.environ.get(k_env_git_repo)
51 if repo_path is None:
52 logging.info(
53 ("You can set the %s environment variable to a .git repository of" % k_env_git_repo) +
54 "your choice - defaulting to the gitpython repository")
55 repo_path = osp.dirname(__file__)
56 # end set some repo path
57 self.gitrorepo = Repo(repo_path, odbt=GitCmdObjectDB, search_parent_directories=True)
58 self.puregitrorepo = Repo(repo_path, odbt=GitDB, search_parent_directories=True)
59
60 def tearDown(self):
61 self.gitrorepo.git.clear_cache()
62 self.gitrorepo = None
63 self.puregitrorepo.git.clear_cache()
64 self.puregitrorepo = None
65
66
67 class TestBigRepoRW(TestBigRepoR):
68
69 """As above, but provides a big repository that we can write to.
70
71 Provides ``self.gitrwrepo`` and ``self.puregitrwrepo``"""
72
73 def setUp(self):
74 self.gitrwrepo = None
75 try:
76 super(TestBigRepoRW, self).setUp()
77 except AttributeError:
78 pass
79 dirname = tempfile.mktemp()
80 os.mkdir(dirname)
81 self.gitrwrepo = self.gitrorepo.clone(dirname, shared=True, bare=True, odbt=GitCmdObjectDB)
82 self.puregitrwrepo = Repo(dirname, odbt=GitDB)
83
84 def tearDown(self):
85 super(TestBigRepoRW, self).tearDown()
86 if self.gitrwrepo is not None:
87 rmtree(self.gitrwrepo.working_dir)
88 self.gitrwrepo.git.clear_cache()
89 self.gitrwrepo = None
90 self.puregitrwrepo.git.clear_cache()
91 self.puregitrwrepo = None
92
93 #} END base classes
+0
-108
git/test/performance/test_commit.py less more
0 # test_performance.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5 from __future__ import print_function
6 from io import BytesIO
7 from time import time
8 import sys
9
10 from .lib import TestBigRepoRW
11 from git import Commit
12 from gitdb import IStream
13 from git.test.test_commit import TestCommitSerialization
14
15
16 class TestPerformance(TestBigRepoRW, TestCommitSerialization):
17
18 def tearDown(self):
19 import gc
20 gc.collect()
21
22 # ref with about 100 commits in its history
23 ref_100 = '0.1.6'
24
25 def _query_commit_info(self, c):
26 c.author
27 c.authored_date
28 c.author_tz_offset
29 c.committer
30 c.committed_date
31 c.committer_tz_offset
32 c.message
33 c.parents
34
35 def test_iteration(self):
36 no = 0
37 nc = 0
38
39 # find the first commit containing the given path - always do a full
40 # iteration ( restricted to the path in question ), but in fact it should
41 # return quite a lot of commits, we just take one and hence abort the operation
42
43 st = time()
44 for c in self.rorepo.iter_commits(self.ref_100):
45 nc += 1
46 self._query_commit_info(c)
47 for obj in c.tree.traverse():
48 obj.size
49 no += 1
50 # END for each object
51 # END for each commit
52 elapsed_time = time() - st
53 print("Traversed %i Trees and a total of %i uncached objects in %s [s] ( %f objs/s )"
54 % (nc, no, elapsed_time, no / elapsed_time), file=sys.stderr)
55
56 def test_commit_traversal(self):
57 # bound to cat-file parsing performance
58 nc = 0
59 st = time()
60 for c in self.gitrorepo.commit().traverse(branch_first=False):
61 nc += 1
62 self._query_commit_info(c)
63 # END for each traversed commit
64 elapsed_time = time() - st
65 print("Traversed %i Commits in %s [s] ( %f commits/s )"
66 % (nc, elapsed_time, nc / elapsed_time), file=sys.stderr)
67
68 def test_commit_iteration(self):
69 # bound to stream parsing performance
70 nc = 0
71 st = time()
72 for c in Commit.iter_items(self.gitrorepo, self.gitrorepo.head):
73 nc += 1
74 self._query_commit_info(c)
75 # END for each traversed commit
76 elapsed_time = time() - st
77 print("Iterated %i Commits in %s [s] ( %f commits/s )"
78 % (nc, elapsed_time, nc / elapsed_time), file=sys.stderr)
79
80 def test_commit_serialization(self):
81 self.assert_commit_serialization(self.gitrwrepo, '58c78e6', True)
82
83 rwrepo = self.gitrwrepo
84 make_object = rwrepo.odb.store
85 # direct serialization - deserialization can be tested afterwards
86 # serialization is probably limited on IO
87 hc = rwrepo.commit(rwrepo.head)
88
89 nc = 5000
90 st = time()
91 for i in range(nc):
92 cm = Commit(rwrepo, Commit.NULL_BIN_SHA, hc.tree,
93 hc.author, hc.authored_date, hc.author_tz_offset,
94 hc.committer, hc.committed_date, hc.committer_tz_offset,
95 str(i), parents=hc.parents, encoding=hc.encoding)
96
97 stream = BytesIO()
98 cm._serialize(stream)
99 slen = stream.tell()
100 stream.seek(0)
101
102 cm.binsha = make_object(IStream(Commit.type, slen, stream)).binsha
103 # END commit creation
104 elapsed = time() - st
105
106 print("Serialized %i commits to loose objects in %f s ( %f commits / s )"
107 % (nc, elapsed, nc / elapsed), file=sys.stderr)
+0
-74
git/test/performance/test_odb.py less more
0 """Performance tests for object store"""
1 from __future__ import print_function
2
3 import sys
4 from time import time
5
6 from .lib import (
7 TestBigRepoR
8 )
9
10
11 class TestObjDBPerformance(TestBigRepoR):
12
13 def test_random_access(self):
14 results = [["Iterate Commits"], ["Iterate Blobs"], ["Retrieve Blob Data"]]
15 for repo in (self.gitrorepo, self.puregitrorepo):
16 # GET COMMITS
17 st = time()
18 root_commit = repo.commit(repo.head)
19 commits = list(root_commit.traverse())
20 nc = len(commits)
21 elapsed = time() - st
22
23 print("%s: Retrieved %i commits from ObjectStore in %g s ( %f commits / s )"
24 % (type(repo.odb), nc, elapsed, nc / elapsed), file=sys.stderr)
25 results[0].append(elapsed)
26
27 # GET TREES
28 # walk all trees of all commits
29 st = time()
30 blobs_per_commit = []
31 nt = 0
32 for commit in commits:
33 tree = commit.tree
34 blobs = []
35 for item in tree.traverse():
36 nt += 1
37 if item.type == 'blob':
38 blobs.append(item)
39 # direct access for speed
40 # END while trees are there for walking
41 blobs_per_commit.append(blobs)
42 # END for each commit
43 elapsed = time() - st
44
45 print("%s: Retrieved %i objects from %i commits in %g s ( %f objects / s )"
46 % (type(repo.odb), nt, len(commits), elapsed, nt / elapsed), file=sys.stderr)
47 results[1].append(elapsed)
48
49 # GET BLOBS
50 st = time()
51 nb = 0
52 too_many = 15000
53 data_bytes = 0
54 for blob_list in blobs_per_commit:
55 for blob in blob_list:
56 data_bytes += len(blob.data_stream.read())
57 # END for each blobsha
58 nb += len(blob_list)
59 if nb > too_many:
60 break
61 # END for each bloblist
62 elapsed = time() - st
63
64 msg = "%s: Retrieved %i blob (%i KiB) and their data in %g s ( %f blobs / s, %f KiB / s )"\
65 % (type(repo.odb), nb, data_bytes / 1000, elapsed, nb / elapsed, (data_bytes / 1000) / elapsed)
66 print(msg, file=sys.stderr)
67 results[2].append(elapsed)
68 # END for each repo type
69
70 # final results
71 for test_name, a, b in results:
72 print("%s: %f s vs %f s, pure is %f times slower" % (test_name, a, b, b / a), file=sys.stderr)
73 # END for each result
+0
-149
git/test/performance/test_streams.py less more
0 """Performance data streaming performance"""
1 from __future__ import print_function
2
3 import os
4 import subprocess
5 import sys
6 from time import time
7
8 from git.test.lib import (
9 with_rw_repo
10 )
11 from git.util import bin_to_hex
12 from gitdb import (
13 LooseObjectDB,
14 IStream
15 )
16 from gitdb.test.lib import make_memory_file
17
18 import os.path as osp
19
20 from .lib import (
21 TestBigRepoR
22 )
23
24
25 class TestObjDBPerformance(TestBigRepoR):
26
27 large_data_size_bytes = 1000 * 1000 * 10 # some MiB should do it
28 moderate_data_size_bytes = 1000 * 1000 * 1 # just 1 MiB
29
30 @with_rw_repo('HEAD', bare=True)
31 def test_large_data_streaming(self, rwrepo):
32 # TODO: This part overlaps with the same file in gitdb.test.performance.test_stream
33 # It should be shared if possible
34 ldb = LooseObjectDB(osp.join(rwrepo.git_dir, 'objects'))
35
36 for randomize in range(2):
37 desc = (randomize and 'random ') or ''
38 print("Creating %s data ..." % desc, file=sys.stderr)
39 st = time()
40 size, stream = make_memory_file(self.large_data_size_bytes, randomize)
41 elapsed = time() - st
42 print("Done (in %f s)" % elapsed, file=sys.stderr)
43
44 # writing - due to the compression it will seem faster than it is
45 st = time()
46 binsha = ldb.store(IStream('blob', size, stream)).binsha
47 elapsed_add = time() - st
48 assert ldb.has_object(binsha)
49 db_file = ldb.readable_db_object_path(bin_to_hex(binsha))
50 fsize_kib = osp.getsize(db_file) / 1000
51
52 size_kib = size / 1000
53 msg = "Added %i KiB (filesize = %i KiB) of %s data to loose odb in %f s ( %f Write KiB / s)"
54 msg %= (size_kib, fsize_kib, desc, elapsed_add, size_kib / elapsed_add)
55 print(msg, file=sys.stderr)
56
57 # reading all at once
58 st = time()
59 ostream = ldb.stream(binsha)
60 shadata = ostream.read()
61 elapsed_readall = time() - st
62
63 stream.seek(0)
64 assert shadata == stream.getvalue()
65 msg = "Read %i KiB of %s data at once from loose odb in %f s ( %f Read KiB / s)"
66 msg %= (size_kib, desc, elapsed_readall, size_kib / elapsed_readall)
67 print(msg, file=sys.stderr)
68
69 # reading in chunks of 1 MiB
70 cs = 512 * 1000
71 chunks = []
72 st = time()
73 ostream = ldb.stream(binsha)
74 while True:
75 data = ostream.read(cs)
76 chunks.append(data)
77 if len(data) < cs:
78 break
79 # END read in chunks
80 elapsed_readchunks = time() - st
81
82 stream.seek(0)
83 assert b''.join(chunks) == stream.getvalue()
84
85 cs_kib = cs / 1000
86 print("Read %i KiB of %s data in %i KiB chunks from loose odb in %f s ( %f Read KiB / s)"
87 % (size_kib, desc, cs_kib, elapsed_readchunks, size_kib / elapsed_readchunks), file=sys.stderr)
88
89 # del db file so git has something to do
90 ostream = None
91 import gc
92 gc.collect()
93 os.remove(db_file)
94
95 # VS. CGIT
96 ##########
97 # CGIT ! Can using the cgit programs be faster ?
98 proc = rwrepo.git.hash_object('-w', '--stdin', as_process=True, istream=subprocess.PIPE)
99
100 # write file - pump everything in at once to be a fast as possible
101 data = stream.getvalue() # cache it
102 st = time()
103 proc.stdin.write(data)
104 proc.stdin.close()
105 gitsha = proc.stdout.read().strip()
106 proc.wait()
107 gelapsed_add = time() - st
108 del(data)
109 assert gitsha == bin_to_hex(binsha) # we do it the same way, right ?
110
111 # as its the same sha, we reuse our path
112 fsize_kib = osp.getsize(db_file) / 1000
113 msg = "Added %i KiB (filesize = %i KiB) of %s data to using git-hash-object in %f s ( %f Write KiB / s)"
114 msg %= (size_kib, fsize_kib, desc, gelapsed_add, size_kib / gelapsed_add)
115 print(msg, file=sys.stderr)
116
117 # compare ...
118 print("Git-Python is %f %% faster than git when adding big %s files"
119 % (100.0 - (elapsed_add / gelapsed_add) * 100, desc), file=sys.stderr)
120
121 # read all
122 st = time()
123 _hexsha, _typename, size, data = rwrepo.git.get_object_data(gitsha)
124 gelapsed_readall = time() - st
125 print("Read %i KiB of %s data at once using git-cat-file in %f s ( %f Read KiB / s)"
126 % (size_kib, desc, gelapsed_readall, size_kib / gelapsed_readall), file=sys.stderr)
127
128 # compare
129 print("Git-Python is %f %% faster than git when reading big %sfiles"
130 % (100.0 - (elapsed_readall / gelapsed_readall) * 100, desc), file=sys.stderr)
131
132 # read chunks
133 st = time()
134 _hexsha, _typename, size, stream = rwrepo.git.stream_object_data(gitsha)
135 while True:
136 data = stream.read(cs)
137 if len(data) < cs:
138 break
139 # END read stream
140 gelapsed_readchunks = time() - st
141 msg = "Read %i KiB of %s data in %i KiB chunks from git-cat-file in %f s ( %f Read KiB / s)"
142 msg %= (size_kib, desc, cs_kib, gelapsed_readchunks, size_kib / gelapsed_readchunks)
143 print(msg, file=sys.stderr)
144
145 # compare
146 print("Git-Python is %f %% faster than git when reading big %s files in chunks"
147 % (100.0 - (elapsed_readchunks / gelapsed_readchunks) * 100, desc), file=sys.stderr)
148 # END for each randomization factor
+0
-37
git/test/test_actor.py less more
0 # test_actor.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5
6 from git.test.lib import TestBase
7 from git import Actor
8
9
10 class TestActor(TestBase):
11
12 def test_from_string_should_separate_name_and_email(self):
13 a = Actor._from_string("Michael Trier <mtrier@example.com>")
14 self.assertEqual("Michael Trier", a.name)
15 self.assertEqual("mtrier@example.com", a.email)
16
17 # base type capabilities
18 assert a == a
19 assert not (a != a)
20 m = set()
21 m.add(a)
22 m.add(a)
23 assert len(m) == 1
24
25 def test_from_string_should_handle_just_name(self):
26 a = Actor._from_string("Michael Trier")
27 self.assertEqual("Michael Trier", a.name)
28 self.assertEqual(None, a.email)
29
30 def test_should_display_representation(self):
31 a = Actor._from_string("Michael Trier <mtrier@example.com>")
32 self.assertEqual('<git.Actor "Michael Trier <mtrier@example.com>">', repr(a))
33
34 def test_str_should_alias_name(self):
35 a = Actor._from_string("Michael Trier <mtrier@example.com>")
36 self.assertEqual(a.name, str(a))
+0
-149
git/test/test_base.py less more
0 # -*- coding: utf-8 -*-
1 # test_base.py
2 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
3 #
4 # This module is part of GitPython and is released under
5 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
6 import os
7 import sys
8 import tempfile
9 from unittest import SkipTest, skipIf
10
11 from git import (
12 Blob,
13 Tree,
14 Commit,
15 TagObject
16 )
17 from git.compat import is_win
18 from git.objects.util import get_object_type_by_name
19 from git.test.lib import (
20 TestBase,
21 with_rw_repo,
22 with_rw_and_rw_remote_repo
23 )
24 from git.util import hex_to_bin
25
26 import git.objects.base as base
27 import os.path as osp
28
29
30 class TestBase(TestBase):
31
32 def tearDown(self):
33 import gc
34 gc.collect()
35
36 type_tuples = (("blob", "8741fc1d09d61f02ffd8cded15ff603eff1ec070", "blob.py"),
37 ("tree", "3a6a5e3eeed3723c09f1ef0399f81ed6b8d82e79", "directory"),
38 ("commit", "4251bd59fb8e11e40c40548cba38180a9536118c", None),
39 ("tag", "e56a60e8e9cd333cfba0140a77cd12b0d9398f10", None))
40
41 def test_base_object(self):
42 # test interface of base object classes
43 types = (Blob, Tree, Commit, TagObject)
44 self.assertEqual(len(types), len(self.type_tuples))
45
46 s = set()
47 num_objs = 0
48 num_index_objs = 0
49 for obj_type, (typename, hexsha, path) in zip(types, self.type_tuples):
50 binsha = hex_to_bin(hexsha)
51 item = None
52 if path is None:
53 item = obj_type(self.rorepo, binsha)
54 else:
55 item = obj_type(self.rorepo, binsha, 0, path)
56 # END handle index objects
57 num_objs += 1
58 self.assertEqual(item.hexsha, hexsha)
59 self.assertEqual(item.type, typename)
60 assert item.size
61 self.assertEqual(item, item)
62 self.assertNotEqual(not item, item)
63 self.assertEqual(str(item), item.hexsha)
64 assert repr(item)
65 s.add(item)
66
67 if isinstance(item, base.IndexObject):
68 num_index_objs += 1
69 if hasattr(item, 'path'): # never runs here
70 assert not item.path.startswith("/") # must be relative
71 assert isinstance(item.mode, int)
72 # END index object check
73
74 # read from stream
75 data_stream = item.data_stream
76 data = data_stream.read()
77 assert data
78
79 tmpfilename = tempfile.mktemp(suffix='test-stream')
80 with open(tmpfilename, 'wb+') as tmpfile:
81 self.assertEqual(item, item.stream_data(tmpfile))
82 tmpfile.seek(0)
83 self.assertEqual(tmpfile.read(), data)
84 os.remove(tmpfilename)
85 # END for each object type to create
86
87 # each has a unique sha
88 self.assertEqual(len(s), num_objs)
89 self.assertEqual(len(s | s), num_objs)
90 self.assertEqual(num_index_objs, 2)
91
92 def test_get_object_type_by_name(self):
93 for tname in base.Object.TYPES:
94 assert base.Object in get_object_type_by_name(tname).mro()
95 # END for each known type
96
97 self.assertRaises(ValueError, get_object_type_by_name, b"doesntexist")
98
99 def test_object_resolution(self):
100 # objects must be resolved to shas so they compare equal
101 self.assertEqual(self.rorepo.head.reference.object, self.rorepo.active_branch.object)
102
103 @with_rw_repo('HEAD', bare=True)
104 def test_with_bare_rw_repo(self, bare_rw_repo):
105 assert bare_rw_repo.config_reader("repository").getboolean("core", "bare")
106 assert osp.isfile(osp.join(bare_rw_repo.git_dir, 'HEAD'))
107
108 @with_rw_repo('0.1.6')
109 def test_with_rw_repo(self, rw_repo):
110 assert not rw_repo.config_reader("repository").getboolean("core", "bare")
111 assert osp.isdir(osp.join(rw_repo.working_tree_dir, 'lib'))
112
113 #@skipIf(HIDE_WINDOWS_FREEZE_ERRORS, "FIXME: Freezes! sometimes...")
114 @with_rw_and_rw_remote_repo('0.1.6')
115 def test_with_rw_remote_and_rw_repo(self, rw_repo, rw_remote_repo):
116 assert not rw_repo.config_reader("repository").getboolean("core", "bare")
117 assert rw_remote_repo.config_reader("repository").getboolean("core", "bare")
118 assert osp.isdir(osp.join(rw_repo.working_tree_dir, 'lib'))
119
120 @skipIf(sys.version_info < (3,) and is_win,
121 "Unicode woes, see https://github.com/gitpython-developers/GitPython/pull/519")
122 @with_rw_repo('0.1.6')
123 def test_add_unicode(self, rw_repo):
124 filename = "שלום.txt"
125
126 file_path = osp.join(rw_repo.working_dir, filename)
127
128 # verify first that we could encode file name in this environment
129 try:
130 file_path.encode(sys.getfilesystemencoding())
131 except UnicodeEncodeError:
132 raise SkipTest("Environment doesn't support unicode filenames")
133
134 with open(file_path, "wb") as fp:
135 fp.write(b'something')
136
137 if is_win:
138 # on windows, there is no way this works, see images on
139 # https://github.com/gitpython-developers/GitPython/issues/147#issuecomment-68881897
140 # Therefore, it must be added using the python implementation
141 rw_repo.index.add([file_path])
142 # However, when the test winds down, rmtree fails to delete this file, which is recognized
143 # as ??? only.
144 else:
145 # on posix, we can just add unicode files without problems
146 rw_repo.git.add(rw_repo.working_dir)
147 # end
148 rw_repo.index.commit('message')
+0
-22
git/test/test_blob.py less more
0 # test_blob.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5
6 from git.test.lib import TestBase
7 from git import Blob
8
9
10 class TestBlob(TestBase):
11
12 def test_mime_type_should_return_mime_type_for_known_types(self):
13 blob = Blob(self.rorepo, **{'binsha': Blob.NULL_BIN_SHA, 'path': 'foo.png'})
14 self.assertEqual("image/png", blob.mime_type)
15
16 def test_mime_type_should_return_text_plain_for_unknown_types(self):
17 blob = Blob(self.rorepo, **{'binsha': Blob.NULL_BIN_SHA, 'path': 'something'})
18 self.assertEqual("text/plain", blob.mime_type)
19
20 def test_nodict(self):
21 self.assertRaises(AttributeError, setattr, self.rorepo.tree()['AUTHORS'], 'someattr', 2)
+0
-393
git/test/test_commit.py less more
0 # -*- coding: utf-8 -*-
1 # test_commit.py
2 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
3 #
4 # This module is part of GitPython and is released under
5 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
6 from __future__ import print_function
7
8 from datetime import datetime
9 from io import BytesIO
10 import re
11 import sys
12 import time
13 from unittest.mock import Mock
14
15 from git import (
16 Commit,
17 Actor,
18 )
19 from git import Repo
20 from git.objects.util import tzoffset, utc
21 from git.repo.fun import touch
22 from git.test.lib import (
23 TestBase,
24 with_rw_repo,
25 fixture_path,
26 StringProcessAdapter
27 )
28 from git.test.lib import with_rw_directory
29 from gitdb import IStream
30
31 import os.path as osp
32
33
34 class TestCommitSerialization(TestBase):
35
36 def assert_commit_serialization(self, rwrepo, commit_id, print_performance_info=False):
37 """traverse all commits in the history of commit identified by commit_id and check
38 if the serialization works.
39 :param print_performance_info: if True, we will show how fast we are"""
40 ns = 0 # num serializations
41 nds = 0 # num deserializations
42
43 st = time.time()
44 for cm in rwrepo.commit(commit_id).traverse():
45 nds += 1
46
47 # assert that we deserialize commits correctly, hence we get the same
48 # sha on serialization
49 stream = BytesIO()
50 cm._serialize(stream)
51 ns += 1
52 streamlen = stream.tell()
53 stream.seek(0)
54
55 istream = rwrepo.odb.store(IStream(Commit.type, streamlen, stream))
56 self.assertEqual(istream.hexsha, cm.hexsha.encode('ascii'))
57
58 nc = Commit(rwrepo, Commit.NULL_BIN_SHA, cm.tree,
59 cm.author, cm.authored_date, cm.author_tz_offset,
60 cm.committer, cm.committed_date, cm.committer_tz_offset,
61 cm.message, cm.parents, cm.encoding)
62
63 self.assertEqual(nc.parents, cm.parents)
64 stream = BytesIO()
65 nc._serialize(stream)
66 ns += 1
67 streamlen = stream.tell()
68 stream.seek(0)
69
70 # reuse istream
71 istream.size = streamlen
72 istream.stream = stream
73 istream.binsha = None
74 nc.binsha = rwrepo.odb.store(istream).binsha
75
76 # if it worked, we have exactly the same contents !
77 self.assertEqual(nc.hexsha, cm.hexsha)
78 # END check commits
79 elapsed = time.time() - st
80
81 if print_performance_info:
82 print("Serialized %i and deserialized %i commits in %f s ( (%f, %f) commits / s"
83 % (ns, nds, elapsed, ns / elapsed, nds / elapsed), file=sys.stderr)
84 # END handle performance info
85
86
87 class TestCommit(TestCommitSerialization):
88
89 def test_bake(self):
90
91 commit = self.rorepo.commit('2454ae89983a4496a445ce347d7a41c0bb0ea7ae')
92 # commits have no dict
93 self.assertRaises(AttributeError, setattr, commit, 'someattr', 1)
94 commit.author # bake
95
96 self.assertEqual("Sebastian Thiel", commit.author.name)
97 self.assertEqual("byronimo@gmail.com", commit.author.email)
98 self.assertEqual(commit.author, commit.committer)
99 assert isinstance(commit.authored_date, int) and isinstance(commit.committed_date, int)
100 assert isinstance(commit.author_tz_offset, int) and isinstance(commit.committer_tz_offset, int)
101 self.assertEqual(commit.message, "Added missing information to docstrings of commit and stats module\n")
102
103 def test_stats(self):
104 commit = self.rorepo.commit('33ebe7acec14b25c5f84f35a664803fcab2f7781')
105 stats = commit.stats
106
107 def check_entries(d):
108 assert isinstance(d, dict)
109 for key in ("insertions", "deletions", "lines"):
110 assert key in d
111 # END assertion helper
112 assert stats.files
113 assert stats.total
114
115 check_entries(stats.total)
116 assert "files" in stats.total
117
118 for _filepath, d in stats.files.items():
119 check_entries(d)
120 # END for each stated file
121
122 # assure data is parsed properly
123 michael = Actor._from_string("Michael Trier <mtrier@gmail.com>")
124 self.assertEqual(commit.author, michael)
125 self.assertEqual(commit.committer, michael)
126 self.assertEqual(commit.authored_date, 1210193388)
127 self.assertEqual(commit.committed_date, 1210193388)
128 self.assertEqual(commit.author_tz_offset, 14400, commit.author_tz_offset)
129 self.assertEqual(commit.committer_tz_offset, 14400, commit.committer_tz_offset)
130 self.assertEqual(commit.message, "initial project\n")
131
132 def test_unicode_actor(self):
133 # assure we can parse unicode actors correctly
134 name = "Üäöß ÄußÉ"
135 self.assertEqual(len(name), 9)
136 special = Actor._from_string("%s <something@this.com>" % name)
137 self.assertEqual(special.name, name)
138 assert isinstance(special.name, str)
139
140 def test_traversal(self):
141 start = self.rorepo.commit("a4d06724202afccd2b5c54f81bcf2bf26dea7fff")
142 first = self.rorepo.commit("33ebe7acec14b25c5f84f35a664803fcab2f7781")
143 p0 = start.parents[0]
144 p1 = start.parents[1]
145 p00 = p0.parents[0]
146 p10 = p1.parents[0]
147
148 # basic branch first, depth first
149 dfirst = start.traverse(branch_first=False)
150 bfirst = start.traverse(branch_first=True)
151 self.assertEqual(next(dfirst), p0)
152 self.assertEqual(next(dfirst), p00)
153
154 self.assertEqual(next(bfirst), p0)
155 self.assertEqual(next(bfirst), p1)
156 self.assertEqual(next(bfirst), p00)
157 self.assertEqual(next(bfirst), p10)
158
159 # at some point, both iterations should stop
160 self.assertEqual(list(bfirst)[-1], first)
161 stoptraverse = self.rorepo.commit("254d04aa3180eb8b8daf7b7ff25f010cd69b4e7d").traverse(as_edge=True)
162 self.assertEqual(len(next(stoptraverse)), 2)
163
164 # ignore self
165 self.assertEqual(next(start.traverse(ignore_self=False)), start)
166
167 # depth
168 self.assertEqual(len(list(start.traverse(ignore_self=False, depth=0))), 1)
169
170 # prune
171 self.assertEqual(next(start.traverse(branch_first=1, prune=lambda i, d: i == p0)), p1)
172
173 # predicate
174 self.assertEqual(next(start.traverse(branch_first=1, predicate=lambda i, d: i == p1)), p1)
175
176 # traversal should stop when the beginning is reached
177 self.assertRaises(StopIteration, next, first.traverse())
178
179 # parents of the first commit should be empty ( as the only parent has a null
180 # sha )
181 self.assertEqual(len(first.parents), 0)
182
183 def test_iteration(self):
184 # we can iterate commits
185 all_commits = Commit.list_items(self.rorepo, self.rorepo.head)
186 assert all_commits
187 self.assertEqual(all_commits, list(self.rorepo.iter_commits()))
188
189 # this includes merge commits
190 mcomit = self.rorepo.commit('d884adc80c80300b4cc05321494713904ef1df2d')
191 assert mcomit in all_commits
192
193 # we can limit the result to paths
194 ltd_commits = list(self.rorepo.iter_commits(paths='CHANGES'))
195 assert ltd_commits and len(ltd_commits) < len(all_commits)
196
197 # show commits of multiple paths, resulting in a union of commits
198 less_ltd_commits = list(Commit.iter_items(self.rorepo, 'master', paths=('CHANGES', 'AUTHORS')))
199 assert len(ltd_commits) < len(less_ltd_commits)
200
201 def test_iter_items(self):
202 # pretty not allowed
203 self.assertRaises(ValueError, Commit.iter_items, self.rorepo, 'master', pretty="raw")
204
205 def test_rev_list_bisect_all(self):
206 """
207 'git rev-list --bisect-all' returns additional information
208 in the commit header. This test ensures that we properly parse it.
209 """
210 revs = self.rorepo.git.rev_list('933d23bf95a5bd1624fbcdf328d904e1fa173474',
211 first_parent=True,
212 bisect_all=True)
213
214 commits = Commit._iter_from_process_or_stream(self.rorepo, StringProcessAdapter(revs.encode('ascii')))
215 expected_ids = (
216 '7156cece3c49544abb6bf7a0c218eb36646fad6d',
217 '1f66cfbbce58b4b552b041707a12d437cc5f400a',
218 '33ebe7acec14b25c5f84f35a664803fcab2f7781',
219 '933d23bf95a5bd1624fbcdf328d904e1fa173474'
220 )
221 for sha1, commit in zip(expected_ids, commits):
222 self.assertEqual(sha1, commit.hexsha)
223
224 @with_rw_directory
225 def test_ambiguous_arg_iteration(self, rw_dir):
226 rw_repo = Repo.init(osp.join(rw_dir, 'test_ambiguous_arg'))
227 path = osp.join(rw_repo.working_tree_dir, 'master')
228 touch(path)
229 rw_repo.index.add([path])
230 rw_repo.index.commit('initial commit')
231 list(rw_repo.iter_commits(rw_repo.head.ref)) # should fail unless bug is fixed
232
233 def test_count(self):
234 self.assertEqual(self.rorepo.tag('refs/tags/0.1.5').commit.count(), 143)
235
236 def test_list(self):
237 # This doesn't work anymore, as we will either attempt getattr with bytes, or compare 20 byte string
238 # with actual 20 byte bytes. This usage makes no sense anyway
239 assert isinstance(Commit.list_items(self.rorepo, '0.1.5', max_count=5)[
240 '5117c9c8a4d3af19a9958677e45cda9269de1541'], Commit)
241
242 def test_str(self):
243 commit = Commit(self.rorepo, Commit.NULL_BIN_SHA)
244 self.assertEqual(Commit.NULL_HEX_SHA, str(commit))
245
246 def test_repr(self):
247 commit = Commit(self.rorepo, Commit.NULL_BIN_SHA)
248 self.assertEqual('<git.Commit "%s">' % Commit.NULL_HEX_SHA, repr(commit))
249
250 def test_equality(self):
251 commit1 = Commit(self.rorepo, Commit.NULL_BIN_SHA)
252 commit2 = Commit(self.rorepo, Commit.NULL_BIN_SHA)
253 commit3 = Commit(self.rorepo, "\1" * 20)
254 self.assertEqual(commit1, commit2)
255 self.assertNotEqual(commit2, commit3)
256
257 def test_iter_parents(self):
258 # should return all but ourselves, even if skip is defined
259 c = self.rorepo.commit('0.1.5')
260 for skip in (0, 1):
261 piter = c.iter_parents(skip=skip)
262 first_parent = next(piter)
263 assert first_parent != c
264 self.assertEqual(first_parent, c.parents[0])
265 # END for each
266
267 def test_name_rev(self):
268 name_rev = self.rorepo.head.commit.name_rev
269 assert isinstance(name_rev, str)
270
271 @with_rw_repo('HEAD', bare=True)
272 def test_serialization(self, rwrepo):
273 # create all commits of our repo
274 self.assert_commit_serialization(rwrepo, '0.1.6')
275
276 def test_serialization_unicode_support(self):
277 self.assertEqual(Commit.default_encoding.lower(), 'utf-8')
278
279 # create a commit with unicode in the message, and the author's name
280 # Verify its serialization and deserialization
281 cmt = self.rorepo.commit('0.1.6')
282 assert isinstance(cmt.message, str) # it automatically decodes it as such
283 assert isinstance(cmt.author.name, str) # same here
284
285 cmt.message = "üäêèß"
286 self.assertEqual(len(cmt.message), 5)
287
288 cmt.author.name = "äüß"
289 self.assertEqual(len(cmt.author.name), 3)
290
291 cstream = BytesIO()
292 cmt._serialize(cstream)
293 cstream.seek(0)
294 assert len(cstream.getvalue())
295
296 ncmt = Commit(self.rorepo, cmt.binsha)
297 ncmt._deserialize(cstream)
298
299 self.assertEqual(cmt.author.name, ncmt.author.name)
300 self.assertEqual(cmt.message, ncmt.message)
301 # actually, it can't be printed in a shell as repr wants to have ascii only
302 # it appears
303 cmt.author.__repr__()
304
305 def test_invalid_commit(self):
306 cmt = self.rorepo.commit()
307 with open(fixture_path('commit_invalid_data'), 'rb') as fd:
308 cmt._deserialize(fd)
309
310 self.assertEqual(cmt.author.name, 'E.Azer Ko�o�o�oculu', cmt.author.name)
311 self.assertEqual(cmt.author.email, 'azer@kodfabrik.com', cmt.author.email)
312
313 def test_gpgsig(self):
314 cmt = self.rorepo.commit()
315 with open(fixture_path('commit_with_gpgsig'), 'rb') as fd:
316 cmt._deserialize(fd)
317
318 fixture_sig = """-----BEGIN PGP SIGNATURE-----
319 Version: GnuPG v1.4.11 (GNU/Linux)
320
321 iQIcBAABAgAGBQJRk8zMAAoJEG5mS6x6i9IjsTEP/0v2Wx/i7dqyKban6XMIhVdj
322 uI0DycfXqnCCZmejidzeao+P+cuK/ZAA/b9fU4MtwkDm2USvnIOrB00W0isxsrED
323 sdv6uJNa2ybGjxBolLrfQcWutxGXLZ1FGRhEvkPTLMHHvVriKoNFXcS7ewxP9MBf
324 NH97K2wauqA+J4BDLDHQJgADCOmLrGTAU+G1eAXHIschDqa6PZMH5nInetYZONDh
325 3SkOOv8VKFIF7gu8X7HC+7+Y8k8U0TW0cjlQ2icinwCc+KFoG6GwXS7u/VqIo1Yp
326 Tack6sxIdK7NXJhV5gAeAOMJBGhO0fHl8UUr96vGEKwtxyZhWf8cuIPOWLk06jA0
327 g9DpLqmy/pvyRfiPci+24YdYRBua/vta+yo/Lp85N7Hu/cpIh+q5WSLvUlv09Dmo
328 TTTG8Hf6s3lEej7W8z2xcNZoB6GwXd8buSDU8cu0I6mEO9sNtAuUOHp2dBvTA6cX
329 PuQW8jg3zofnx7CyNcd3KF3nh2z8mBcDLgh0Q84srZJCPRuxRcp9ylggvAG7iaNd
330 XMNvSK8IZtWLkx7k3A3QYt1cN4y1zdSHLR2S+BVCEJea1mvUE+jK5wiB9S4XNtKm
331 BX/otlTa8pNE3fWYBxURvfHnMY4i3HQT7Bc1QjImAhMnyo2vJk4ORBJIZ1FTNIhJ
332 JzJMZDRLQLFvnzqZuCjE
333 =przd
334 -----END PGP SIGNATURE-----"""
335 self.assertEqual(cmt.gpgsig, fixture_sig)
336
337 cmt.gpgsig = "<test\ndummy\nsig>"
338 assert cmt.gpgsig != fixture_sig
339
340 cstream = BytesIO()
341 cmt._serialize(cstream)
342 assert re.search(r"^gpgsig <test\n dummy\n sig>$", cstream.getvalue().decode('ascii'), re.MULTILINE)
343
344 self.assert_gpgsig_deserialization(cstream)
345
346 cstream.seek(0)
347 cmt.gpgsig = None
348 cmt._deserialize(cstream)
349 self.assertEqual(cmt.gpgsig, "<test\ndummy\nsig>")
350
351 cmt.gpgsig = None
352 cstream = BytesIO()
353 cmt._serialize(cstream)
354 assert not re.search(r"^gpgsig ", cstream.getvalue().decode('ascii'), re.MULTILINE)
355
356 def assert_gpgsig_deserialization(self, cstream):
357 assert 'gpgsig' in 'precondition: need gpgsig'
358
359 class RepoMock:
360 def __init__(self, bytestr):
361 self.bytestr = bytestr
362
363 @property
364 def odb(self):
365 class ODBMock:
366 def __init__(self, bytestr):
367 self.bytestr = bytestr
368
369 def stream(self, *args):
370 stream = Mock(spec_set=['read'], return_value=self.bytestr)
371 stream.read.return_value = self.bytestr
372 return ('binsha', 'typename', 'size', stream)
373
374 return ODBMock(self.bytestr)
375
376 repo_mock = RepoMock(cstream.getvalue())
377 for field in Commit.__slots__:
378 c = Commit(repo_mock, b'x' * 20)
379 assert getattr(c, field) is not None
380
381 def test_datetimes(self):
382 commit = self.rorepo.commit('4251bd5')
383 self.assertEqual(commit.authored_date, 1255018625)
384 self.assertEqual(commit.committed_date, 1255026171)
385 self.assertEqual(commit.authored_datetime,
386 datetime(2009, 10, 8, 18, 17, 5, tzinfo=tzoffset(-7200)), commit.authored_datetime) # noqa
387 self.assertEqual(commit.authored_datetime,
388 datetime(2009, 10, 8, 16, 17, 5, tzinfo=utc), commit.authored_datetime)
389 self.assertEqual(commit.committed_datetime,
390 datetime(2009, 10, 8, 20, 22, 51, tzinfo=tzoffset(-7200)))
391 self.assertEqual(commit.committed_datetime,
392 datetime(2009, 10, 8, 18, 22, 51, tzinfo=utc), commit.committed_datetime)
+0
-373
git/test/test_config.py less more
0 # test_config.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5
6 import glob
7 import io
8
9 from git import (
10 GitConfigParser
11 )
12 from git.config import _OMD, cp
13 from git.test.lib import (
14 TestCase,
15 fixture_path,
16 SkipTest,
17 )
18 from git.test.lib import with_rw_directory
19
20 import os.path as osp
21 from git.util import rmfile
22
23
24 _tc_lock_fpaths = osp.join(osp.dirname(__file__), 'fixtures/*.lock')
25
26
27 def _rm_lock_files():
28 for lfp in glob.glob(_tc_lock_fpaths):
29 rmfile(lfp)
30
31
32 class TestBase(TestCase):
33 def setUp(self):
34 _rm_lock_files()
35
36 def tearDown(self):
37 for lfp in glob.glob(_tc_lock_fpaths):
38 if osp.isfile(lfp):
39 raise AssertionError('Previous TC left hanging git-lock file: {}'.format(lfp))
40
41 def _to_memcache(self, file_path):
42 with open(file_path, "rb") as fp:
43 sio = io.BytesIO(fp.read())
44 sio.name = file_path
45 return sio
46
47 def test_read_write(self):
48 # writer must create the exact same file as the one read before
49 for filename in ("git_config", "git_config_global"):
50 file_obj = self._to_memcache(fixture_path(filename))
51 with GitConfigParser(file_obj, read_only=False) as w_config:
52 w_config.read() # enforce reading
53 assert w_config._sections
54 w_config.write() # enforce writing
55
56 # we stripped lines when reading, so the results differ
57 assert file_obj.getvalue()
58 self.assertEqual(file_obj.getvalue(), self._to_memcache(fixture_path(filename)).getvalue())
59
60 # creating an additional config writer must fail due to exclusive access
61 with self.assertRaises(IOError):
62 GitConfigParser(file_obj, read_only=False)
63
64 # should still have a lock and be able to make changes
65 assert w_config._lock._has_lock()
66
67 # changes should be written right away
68 sname = "my_section"
69 oname = "mykey"
70 val = "myvalue"
71 w_config.add_section(sname)
72 assert w_config.has_section(sname)
73 w_config.set(sname, oname, val)
74 assert w_config.has_option(sname, oname)
75 assert w_config.get(sname, oname) == val
76
77 sname_new = "new_section"
78 oname_new = "new_key"
79 ival = 10
80 w_config.set_value(sname_new, oname_new, ival)
81 assert w_config.get_value(sname_new, oname_new) == ival
82
83 file_obj.seek(0)
84 r_config = GitConfigParser(file_obj, read_only=True)
85 assert r_config.has_section(sname)
86 assert r_config.has_option(sname, oname)
87 assert r_config.get(sname, oname) == val
88 # END for each filename
89
90 def test_includes_order(self):
91 with GitConfigParser(list(map(fixture_path, ("git_config", "git_config_global")))) as r_config:
92 r_config.read() # enforce reading
93 # Simple inclusions, again checking them taking precedence
94 assert r_config.get_value('sec', 'var0') == "value0_included"
95 # This one should take the git_config_global value since included
96 # values must be considered as soon as they get them
97 assert r_config.get_value('diff', 'tool') == "meld"
98 try:
99 assert r_config.get_value('sec', 'var1') == "value1_main"
100 except AssertionError:
101 raise SkipTest(
102 'Known failure -- included values are not in effect right away'
103 )
104
105 @with_rw_directory
106 def test_lock_reentry(self, rw_dir):
107 fpl = osp.join(rw_dir, 'l')
108 gcp = GitConfigParser(fpl, read_only=False)
109 with gcp as cw:
110 cw.set_value('include', 'some_value', 'a')
111 # entering again locks the file again...
112 with gcp as cw:
113 cw.set_value('include', 'some_other_value', 'b')
114 # ...so creating an additional config writer must fail due to exclusive access
115 with self.assertRaises(IOError):
116 GitConfigParser(fpl, read_only=False)
117 # but work when the lock is removed
118 with GitConfigParser(fpl, read_only=False):
119 assert osp.exists(fpl)
120 # reentering with an existing lock must fail due to exclusive access
121 with self.assertRaises(IOError):
122 gcp.__enter__()
123
124 def test_multi_line_config(self):
125 file_obj = self._to_memcache(fixture_path("git_config_with_comments"))
126 with GitConfigParser(file_obj, read_only=False) as config:
127 ev = "ruby -e '\n"
128 ev += " system %(git), %(merge-file), %(--marker-size=%L), %(%A), %(%O), %(%B)\n"
129 ev += " b = File.read(%(%A))\n"
130 ev += " b.sub!(/^<+ .*\\nActiveRecord::Schema\\.define.:version => (\\d+). do\\n=+\\nActiveRecord::Schema\\." # noqa E501
131 ev += "define.:version => (\\d+). do\\n>+ .*/) do\n"
132 ev += " %(ActiveRecord::Schema.define(:version => #{[$1, $2].max}) do)\n"
133 ev += " end\n"
134 ev += " File.open(%(%A), %(w)) {|f| f.write(b)}\n"
135 ev += " exit 1 if b.include?(%(<)*%L)'"
136 self.assertEqual(config.get('merge "railsschema"', 'driver'), ev)
137 self.assertEqual(config.get('alias', 'lg'),
138 "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset'"
139 " --abbrev-commit --date=relative")
140 self.assertEqual(len(config.sections()), 23)
141
142 def test_base(self):
143 path_repo = fixture_path("git_config")
144 path_global = fixture_path("git_config_global")
145 r_config = GitConfigParser([path_repo, path_global], read_only=True)
146 assert r_config.read_only
147 num_sections = 0
148 num_options = 0
149
150 # test reader methods
151 assert r_config._is_initialized is False
152 for section in r_config.sections():
153 num_sections += 1
154 for option in r_config.options(section):
155 num_options += 1
156 val = r_config.get(section, option)
157 val_typed = r_config.get_value(section, option)
158 assert isinstance(val_typed, (bool, int, float, str))
159 assert val
160 assert "\n" not in option
161 assert "\n" not in val
162
163 # writing must fail
164 with self.assertRaises(IOError):
165 r_config.set(section, option, None)
166 with self.assertRaises(IOError):
167 r_config.remove_option(section, option)
168 # END for each option
169 with self.assertRaises(IOError):
170 r_config.remove_section(section)
171 # END for each section
172 assert num_sections and num_options
173 assert r_config._is_initialized is True
174
175 # get value which doesnt exist, with default
176 default = "my default value"
177 assert r_config.get_value("doesnt", "exist", default) == default
178
179 # it raises if there is no default though
180 with self.assertRaises(cp.NoSectionError):
181 r_config.get_value("doesnt", "exist")
182
183 @with_rw_directory
184 def test_config_include(self, rw_dir):
185 def write_test_value(cw, value):
186 cw.set_value(value, 'value', value)
187 # end
188
189 def check_test_value(cr, value):
190 assert cr.get_value(value, 'value') == value
191 # end
192
193 # PREPARE CONFIG FILE A
194 fpa = osp.join(rw_dir, 'a')
195 with GitConfigParser(fpa, read_only=False) as cw:
196 write_test_value(cw, 'a')
197
198 fpb = osp.join(rw_dir, 'b')
199 fpc = osp.join(rw_dir, 'c')
200 cw.set_value('include', 'relative_path_b', 'b')
201 cw.set_value('include', 'doesntexist', 'foobar')
202 cw.set_value('include', 'relative_cycle_a_a', 'a')
203 cw.set_value('include', 'absolute_cycle_a_a', fpa)
204 assert osp.exists(fpa)
205
206 # PREPARE CONFIG FILE B
207 with GitConfigParser(fpb, read_only=False) as cw:
208 write_test_value(cw, 'b')
209 cw.set_value('include', 'relative_cycle_b_a', 'a')
210 cw.set_value('include', 'absolute_cycle_b_a', fpa)
211 cw.set_value('include', 'relative_path_c', 'c')
212 cw.set_value('include', 'absolute_path_c', fpc)
213
214 # PREPARE CONFIG FILE C
215 with GitConfigParser(fpc, read_only=False) as cw:
216 write_test_value(cw, 'c')
217
218 with GitConfigParser(fpa, read_only=True) as cr:
219 for tv in ('a', 'b', 'c'):
220 check_test_value(cr, tv)
221 # end for each test to verify
222 assert len(cr.items('include')) == 8, "Expected all include sections to be merged"
223
224 # test writable config writers - assure write-back doesn't involve includes
225 with GitConfigParser(fpa, read_only=False, merge_includes=True) as cw:
226 tv = 'x'
227 write_test_value(cw, tv)
228
229 with GitConfigParser(fpa, read_only=True) as cr:
230 with self.assertRaises(cp.NoSectionError):
231 check_test_value(cr, tv)
232
233 # But can make it skip includes altogether, and thus allow write-backs
234 with GitConfigParser(fpa, read_only=False, merge_includes=False) as cw:
235 write_test_value(cw, tv)
236
237 with GitConfigParser(fpa, read_only=True) as cr:
238 check_test_value(cr, tv)
239
240 def test_rename(self):
241 file_obj = self._to_memcache(fixture_path('git_config'))
242 with GitConfigParser(file_obj, read_only=False, merge_includes=False) as cw:
243 with self.assertRaises(ValueError):
244 cw.rename_section("doesntexist", "foo")
245 with self.assertRaises(ValueError):
246 cw.rename_section("core", "include")
247
248 nn = "bee"
249 assert cw.rename_section('core', nn) is cw
250 assert not cw.has_section('core')
251 assert len(cw.items(nn)) == 4
252
253 def test_complex_aliases(self):
254 file_obj = self._to_memcache(fixture_path('.gitconfig'))
255 with GitConfigParser(file_obj, read_only=False) as w_config:
256 self.assertEqual(w_config.get('alias', 'rbi'), '"!g() { git rebase -i origin/${1:-master} ; } ; g"')
257 self.assertEqual(file_obj.getvalue(), self._to_memcache(fixture_path('.gitconfig')).getvalue())
258
259 def test_empty_config_value(self):
260 cr = GitConfigParser(fixture_path('git_config_with_empty_value'), read_only=True)
261
262 assert cr.get_value('core', 'filemode'), "Should read keys with values"
263
264 with self.assertRaises(cp.NoOptionError):
265 cr.get_value('color', 'ui')
266
267 def test_multiple_values(self):
268 file_obj = self._to_memcache(fixture_path('git_config_multiple'))
269 with GitConfigParser(file_obj, read_only=False) as cw:
270 self.assertEqual(cw.get('section0', 'option0'), 'value0')
271 self.assertEqual(cw.get_values('section0', 'option0'), ['value0'])
272 self.assertEqual(cw.items('section0'), [('option0', 'value0')])
273
274 # Where there are multiple values, "get" returns the last.
275 self.assertEqual(cw.get('section1', 'option1'), 'value1b')
276 self.assertEqual(cw.get_values('section1', 'option1'),
277 ['value1a', 'value1b'])
278 self.assertEqual(cw.items('section1'),
279 [('option1', 'value1b'),
280 ('other_option1', 'other_value1')])
281 self.assertEqual(cw.items_all('section1'),
282 [('option1', ['value1a', 'value1b']),
283 ('other_option1', ['other_value1'])])
284 with self.assertRaises(KeyError):
285 cw.get_values('section1', 'missing')
286
287 self.assertEqual(cw.get_values('section1', 'missing', 1), [1])
288 self.assertEqual(cw.get_values('section1', 'missing', 's'), ['s'])
289
290 def test_multiple_values_rename(self):
291 file_obj = self._to_memcache(fixture_path('git_config_multiple'))
292 with GitConfigParser(file_obj, read_only=False) as cw:
293 cw.rename_section('section1', 'section2')
294 cw.write()
295 file_obj.seek(0)
296 cr = GitConfigParser(file_obj, read_only=True)
297 self.assertEqual(cr.get_value('section2', 'option1'), 'value1b')
298 self.assertEqual(cr.get_values('section2', 'option1'),
299 ['value1a', 'value1b'])
300 self.assertEqual(cr.items('section2'),
301 [('option1', 'value1b'),
302 ('other_option1', 'other_value1')])
303 self.assertEqual(cr.items_all('section2'),
304 [('option1', ['value1a', 'value1b']),
305 ('other_option1', ['other_value1'])])
306
307 def test_multiple_to_single(self):
308 file_obj = self._to_memcache(fixture_path('git_config_multiple'))
309 with GitConfigParser(file_obj, read_only=False) as cw:
310 cw.set_value('section1', 'option1', 'value1c')
311
312 cw.write()
313 file_obj.seek(0)
314 cr = GitConfigParser(file_obj, read_only=True)
315 self.assertEqual(cr.get_value('section1', 'option1'), 'value1c')
316 self.assertEqual(cr.get_values('section1', 'option1'), ['value1c'])
317 self.assertEqual(cr.items('section1'),
318 [('option1', 'value1c'),
319 ('other_option1', 'other_value1')])
320 self.assertEqual(cr.items_all('section1'),
321 [('option1', ['value1c']),
322 ('other_option1', ['other_value1'])])
323
324 def test_single_to_multiple(self):
325 file_obj = self._to_memcache(fixture_path('git_config_multiple'))
326 with GitConfigParser(file_obj, read_only=False) as cw:
327 cw.add_value('section1', 'other_option1', 'other_value1a')
328
329 cw.write()
330 file_obj.seek(0)
331 cr = GitConfigParser(file_obj, read_only=True)
332 self.assertEqual(cr.get_value('section1', 'option1'), 'value1b')
333 self.assertEqual(cr.get_values('section1', 'option1'),
334 ['value1a', 'value1b'])
335 self.assertEqual(cr.get_value('section1', 'other_option1'),
336 'other_value1a')
337 self.assertEqual(cr.get_values('section1', 'other_option1'),
338 ['other_value1', 'other_value1a'])
339 self.assertEqual(cr.items('section1'),
340 [('option1', 'value1b'),
341 ('other_option1', 'other_value1a')])
342 self.assertEqual(
343 cr.items_all('section1'),
344 [('option1', ['value1a', 'value1b']),
345 ('other_option1', ['other_value1', 'other_value1a'])])
346
347 def test_add_to_multiple(self):
348 file_obj = self._to_memcache(fixture_path('git_config_multiple'))
349 with GitConfigParser(file_obj, read_only=False) as cw:
350 cw.add_value('section1', 'option1', 'value1c')
351 cw.write()
352 file_obj.seek(0)
353 cr = GitConfigParser(file_obj, read_only=True)
354 self.assertEqual(cr.get_value('section1', 'option1'), 'value1c')
355 self.assertEqual(cr.get_values('section1', 'option1'),
356 ['value1a', 'value1b', 'value1c'])
357 self.assertEqual(cr.items('section1'),
358 [('option1', 'value1c'),
359 ('other_option1', 'other_value1')])
360 self.assertEqual(cr.items_all('section1'),
361 [('option1', ['value1a', 'value1b', 'value1c']),
362 ('other_option1', ['other_value1'])])
363
364 def test_setlast(self):
365 # Test directly, not covered by higher-level tests.
366 omd = _OMD()
367 omd.setlast('key', 'value1')
368 self.assertEqual(omd['key'], 'value1')
369 self.assertEqual(omd.getall('key'), ['value1'])
370 omd.setlast('key', 'value2')
371 self.assertEqual(omd['key'], 'value2')
372 self.assertEqual(omd.getall('key'), ['value2'])
+0
-27
git/test/test_db.py less more
0 # test_repo.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5 from git.db import GitCmdObjectDB
6 from git.exc import BadObject
7 from git.test.lib import TestBase
8 from git.util import bin_to_hex
9
10 import os.path as osp
11
12
13 class TestDB(TestBase):
14
15 def test_base(self):
16 gdb = GitCmdObjectDB(osp.join(self.rorepo.git_dir, 'objects'), self.rorepo.git)
17
18 # partial to complete - works with everything
19 hexsha = bin_to_hex(gdb.partial_to_complete_sha_hex("0.1.6"))
20 assert len(hexsha) == 40
21
22 assert bin_to_hex(gdb.partial_to_complete_sha_hex(hexsha[:20])) == hexsha
23
24 # fails with BadObject
25 for invalid_rev in ("0000", "bad/ref", "super bad"):
26 self.assertRaises(BadObject, gdb.partial_to_complete_sha_hex, invalid_rev)
+0
-369
git/test/test_diff.py less more
0 # coding: utf-8
1 # test_diff.py
2 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
3 #
4 # This module is part of GitPython and is released under
5 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
6 import ddt
7 import shutil
8 import tempfile
9 from git import (
10 Repo,
11 GitCommandError,
12 Diff,
13 DiffIndex,
14 NULL_TREE,
15 Submodule,
16 )
17 from git.cmd import Git
18 from git.test.lib import (
19 TestBase,
20 StringProcessAdapter,
21 fixture,
22 )
23 from git.test.lib import with_rw_directory
24
25 import os.path as osp
26
27
28 @ddt.ddt
29 class TestDiff(TestBase):
30
31 def setUp(self):
32 self.repo_dir = tempfile.mkdtemp()
33 self.submodule_dir = tempfile.mkdtemp()
34
35 def tearDown(self):
36 import gc
37 gc.collect()
38 shutil.rmtree(self.repo_dir)
39 shutil.rmtree(self.submodule_dir)
40
41 def _assert_diff_format(self, diffs):
42 # verify that the format of the diff is sane
43 for diff in diffs:
44 if diff.a_mode:
45 assert isinstance(diff.a_mode, int)
46 if diff.b_mode:
47 assert isinstance(diff.b_mode, int)
48
49 if diff.a_blob:
50 assert not diff.a_blob.path.endswith('\n')
51 if diff.b_blob:
52 assert not diff.b_blob.path.endswith('\n')
53 # END for each diff
54 return diffs
55
56 @with_rw_directory
57 def test_diff_with_staged_file(self, rw_dir):
58 # SETUP INDEX WITH MULTIPLE STAGES
59 r = Repo.init(rw_dir)
60 fp = osp.join(rw_dir, 'hello.txt')
61 with open(fp, 'w') as fs:
62 fs.write("hello world")
63 r.git.add(Git.polish_url(fp))
64 r.git.commit(message="init")
65
66 with open(fp, 'w') as fs:
67 fs.write("Hola Mundo")
68 r.git.add(Git.polish_url(fp))
69 self.assertEqual(len(r.index.diff("HEAD", create_patch=True)), 1,
70 "create_patch should generate patch of diff to HEAD")
71 r.git.commit(message="change on master")
72 self.assertEqual(len(r.index.diff("HEAD", create_patch=True)), 0,
73 "create_patch should generate no patch, already on HEAD")
74
75 r.git.checkout('HEAD~1', b='topic')
76 with open(fp, 'w') as fs:
77 fs.write("Hallo Welt")
78 r.git.commit(all=True, message="change on topic branch")
79
80 # there must be a merge-conflict
81 with self.assertRaises(GitCommandError):
82 r.git.cherry_pick('master')
83
84 # Now do the actual testing - this should just work
85 self.assertEqual(len(r.index.diff(None)), 2)
86
87 self.assertEqual(len(r.index.diff(None, create_patch=True)), 0,
88 "This should work, but doesn't right now ... it's OK")
89
90 def test_list_from_string_new_mode(self):
91 output = StringProcessAdapter(fixture('diff_new_mode'))
92 diffs = Diff._index_from_patch_format(self.rorepo, output)
93 self._assert_diff_format(diffs)
94
95 self.assertEqual(1, len(diffs))
96 self.assertEqual(8, len(diffs[0].diff.splitlines()))
97
98 def test_diff_with_rename(self):
99 output = StringProcessAdapter(fixture('diff_rename'))
100 diffs = Diff._index_from_patch_format(self.rorepo, output)
101 self._assert_diff_format(diffs)
102
103 self.assertEqual(1, len(diffs))
104
105 diff = diffs[0]
106 self.assertTrue(diff.renamed_file)
107 self.assertTrue(diff.renamed)
108 self.assertEqual(diff.rename_from, 'Jérôme')
109 self.assertEqual(diff.rename_to, 'müller')
110 self.assertEqual(diff.raw_rename_from, b'J\xc3\xa9r\xc3\xb4me')
111 self.assertEqual(diff.raw_rename_to, b'm\xc3\xbcller')
112 assert isinstance(str(diff), str)
113
114 output = StringProcessAdapter(fixture('diff_rename_raw'))
115 diffs = Diff._index_from_raw_format(self.rorepo, output)
116 self.assertEqual(len(diffs), 1)
117 diff = diffs[0]
118 self.assertIsNotNone(diff.renamed_file)
119 self.assertIsNotNone(diff.renamed)
120 self.assertEqual(diff.rename_from, 'this')
121 self.assertEqual(diff.rename_to, 'that')
122 self.assertEqual(diff.change_type, 'R')
123 self.assertEqual(diff.score, 100)
124 self.assertEqual(len(list(diffs.iter_change_type('R'))), 1)
125
126 def test_diff_with_copied_file(self):
127 output = StringProcessAdapter(fixture('diff_copied_mode'))
128 diffs = Diff._index_from_patch_format(self.rorepo, output)
129 self._assert_diff_format(diffs)
130
131 self.assertEqual(1, len(diffs))
132
133 diff = diffs[0]
134 self.assertTrue(diff.copied_file)
135 self.assertTrue(diff.a_path, 'test1.txt')
136 self.assertTrue(diff.b_path, 'test2.txt')
137 assert isinstance(str(diff), str)
138
139 output = StringProcessAdapter(fixture('diff_copied_mode_raw'))
140 diffs = Diff._index_from_raw_format(self.rorepo, output)
141 self.assertEqual(len(diffs), 1)
142 diff = diffs[0]
143 self.assertEqual(diff.change_type, 'C')
144 self.assertEqual(diff.score, 100)
145 self.assertEqual(diff.a_path, 'test1.txt')
146 self.assertEqual(diff.b_path, 'test2.txt')
147 self.assertEqual(len(list(diffs.iter_change_type('C'))), 1)
148
149 def test_diff_with_change_in_type(self):
150 output = StringProcessAdapter(fixture('diff_change_in_type'))
151 diffs = Diff._index_from_patch_format(self.rorepo, output)
152 self._assert_diff_format(diffs)
153 self.assertEqual(2, len(diffs))
154
155 diff = diffs[0]
156 self.assertIsNotNone(diff.deleted_file)
157 self.assertEqual(diff.a_path, 'this')
158 self.assertEqual(diff.b_path, 'this')
159 assert isinstance(str(diff), str)
160
161 diff = diffs[1]
162 self.assertEqual(diff.a_path, None)
163 self.assertEqual(diff.b_path, 'this')
164 self.assertIsNotNone(diff.new_file)
165 assert isinstance(str(diff), str)
166
167 output = StringProcessAdapter(fixture('diff_change_in_type_raw'))
168 diffs = Diff._index_from_raw_format(self.rorepo, output)
169 self.assertEqual(len(diffs), 1)
170 diff = diffs[0]
171 self.assertEqual(diff.rename_from, None)
172 self.assertEqual(diff.rename_to, None)
173 self.assertEqual(diff.change_type, 'T')
174 self.assertEqual(len(list(diffs.iter_change_type('T'))), 1)
175
176 def test_diff_of_modified_files_not_added_to_the_index(self):
177 output = StringProcessAdapter(fixture('diff_abbrev-40_full-index_M_raw_no-color'))
178 diffs = Diff._index_from_raw_format(self.rorepo, output)
179
180 self.assertEqual(len(diffs), 1, 'one modification')
181 self.assertEqual(len(list(diffs.iter_change_type('M'))), 1, 'one modification')
182 self.assertEqual(diffs[0].change_type, 'M')
183 self.assertIsNone(diffs[0].b_blob,)
184
185 @ddt.data(
186 (Diff._index_from_patch_format, 'diff_patch_binary'),
187 (Diff._index_from_raw_format, 'diff_raw_binary')
188 )
189 def test_binary_diff(self, case):
190 method, file_name = case
191 res = method(None, StringProcessAdapter(fixture(file_name)))
192 self.assertEqual(len(res), 1)
193 self.assertEqual(len(list(res.iter_change_type('M'))), 1)
194 if res[0].diff:
195 self.assertEqual(res[0].diff,
196 b"Binary files a/rps and b/rps differ\n",
197 "in patch mode, we get a diff text")
198 self.assertIsNotNone(str(res[0]), "This call should just work")
199
200 def test_diff_index(self):
201 output = StringProcessAdapter(fixture('diff_index_patch'))
202 res = Diff._index_from_patch_format(None, output)
203 self.assertEqual(len(res), 6)
204 for dr in res:
205 self.assertTrue(dr.diff.startswith(b'@@'), dr)
206 self.assertIsNotNone(str(dr), "Diff to string conversion should be possible")
207 # end for each diff
208
209 dr = res[3]
210 assert dr.diff.endswith(b"+Binary files a/rps and b/rps differ\n")
211
212 def test_diff_index_raw_format(self):
213 output = StringProcessAdapter(fixture('diff_index_raw'))
214 res = Diff._index_from_raw_format(None, output)
215 self.assertIsNotNone(res[0].deleted_file)
216 self.assertIsNone(res[0].b_path,)
217
218 def test_diff_initial_commit(self):
219 initial_commit = self.rorepo.commit('33ebe7acec14b25c5f84f35a664803fcab2f7781')
220
221 # Without creating a patch...
222 diff_index = initial_commit.diff(NULL_TREE)
223 self.assertEqual(diff_index[0].b_path, 'CHANGES')
224 self.assertIsNotNone(diff_index[0].new_file)
225 self.assertEqual(diff_index[0].diff, '')
226
227 # ...and with creating a patch
228 diff_index = initial_commit.diff(NULL_TREE, create_patch=True)
229 self.assertIsNone(diff_index[0].a_path, repr(diff_index[0].a_path))
230 self.assertEqual(diff_index[0].b_path, 'CHANGES', repr(diff_index[0].b_path))
231 self.assertIsNotNone(diff_index[0].new_file)
232 self.assertEqual(diff_index[0].diff, fixture('diff_initial'))
233
234 def test_diff_unsafe_paths(self):
235 output = StringProcessAdapter(fixture('diff_patch_unsafe_paths'))
236 res = Diff._index_from_patch_format(None, output)
237
238 # The "Additions"
239 self.assertEqual(res[0].b_path, 'path/ starting with a space')
240 self.assertEqual(res[1].b_path, 'path/"with-quotes"')
241 self.assertEqual(res[2].b_path, "path/'with-single-quotes'")
242 self.assertEqual(res[3].b_path, 'path/ending in a space ')
243 self.assertEqual(res[4].b_path, 'path/with\ttab')
244 self.assertEqual(res[5].b_path, 'path/with\nnewline')
245 self.assertEqual(res[6].b_path, 'path/with spaces')
246 self.assertEqual(res[7].b_path, 'path/with-question-mark?')
247 self.assertEqual(res[8].b_path, 'path/¯\\_(ツ)_|¯')
248 self.assertEqual(res[9].b_path, 'path/💩.txt')
249 self.assertEqual(res[9].b_rawpath, b'path/\xf0\x9f\x92\xa9.txt')
250 self.assertEqual(res[10].b_path, 'path/�-invalid-unicode-path.txt')
251 self.assertEqual(res[10].b_rawpath, b'path/\x80-invalid-unicode-path.txt')
252
253 # The "Moves"
254 # NOTE: The path prefixes a/ and b/ here are legit! We're actually
255 # verifying that it's not "a/a/" that shows up, see the fixture data.
256 self.assertEqual(res[11].a_path, 'a/with spaces') # NOTE: path a/ here legit!
257 self.assertEqual(res[11].b_path, 'b/with some spaces') # NOTE: path b/ here legit!
258 self.assertEqual(res[12].a_path, 'a/ending in a space ')
259 self.assertEqual(res[12].b_path, 'b/ending with space ')
260 self.assertEqual(res[13].a_path, 'a/"with-quotes"')
261 self.assertEqual(res[13].b_path, 'b/"with even more quotes"')
262
263 def test_diff_patch_format(self):
264 # test all of the 'old' format diffs for completness - it should at least
265 # be able to deal with it
266 fixtures = ("diff_2", "diff_2f", "diff_f", "diff_i", "diff_mode_only",
267 "diff_new_mode", "diff_numstat", "diff_p", "diff_rename",
268 "diff_tree_numstat_root", "diff_patch_unsafe_paths")
269
270 for fixture_name in fixtures:
271 diff_proc = StringProcessAdapter(fixture(fixture_name))
272 Diff._index_from_patch_format(self.rorepo, diff_proc)
273 # END for each fixture
274
275 def test_diff_with_spaces(self):
276 data = StringProcessAdapter(fixture('diff_file_with_spaces'))
277 diff_index = Diff._index_from_patch_format(self.rorepo, data)
278 self.assertIsNone(diff_index[0].a_path, repr(diff_index[0].a_path))
279 self.assertEqual(diff_index[0].b_path, 'file with spaces', repr(diff_index[0].b_path))
280
281 def test_diff_submodule(self):
282 """Test that diff is able to correctly diff commits that cover submodule changes"""
283 # Init a temp git repo that will be referenced as a submodule
284 sub = Repo.init(self.submodule_dir)
285 with open(self.submodule_dir + "/subfile", "w") as sub_subfile:
286 sub_subfile.write("")
287 sub.index.add(["subfile"])
288 sub.index.commit("first commit")
289
290 # Init a temp git repo that will incorporate the submodule
291 repo = Repo.init(self.repo_dir)
292 with open(self.repo_dir + "/test", "w") as foo_test:
293 foo_test.write("")
294 repo.index.add(['test'])
295 Submodule.add(repo, "subtest", "sub", url="file://" + self.submodule_dir)
296 repo.index.commit("first commit")
297 repo.create_tag('1')
298
299 # Add a commit to the submodule
300 submodule = repo.submodule('subtest')
301 with open(self.repo_dir + "/sub/subfile", "w") as foo_sub_subfile:
302 foo_sub_subfile.write("blub")
303 submodule.module().index.add(["subfile"])
304 submodule.module().index.commit("changed subfile")
305 submodule.binsha = submodule.module().head.commit.binsha
306
307 # Commit submodule updates in parent repo
308 repo.index.add([submodule])
309 repo.index.commit("submodule changed")
310 repo.create_tag('2')
311
312 diff = repo.commit('1').diff(repo.commit('2'))[0]
313 # If diff is unable to find the commit hashes (looks in wrong repo) the *_blob.size
314 # property will be a string containing exception text, an int indicates success
315 self.assertIsInstance(diff.a_blob.size, int)
316 self.assertIsInstance(diff.b_blob.size, int)
317
318 def test_diff_interface(self):
319 # test a few variations of the main diff routine
320 assertion_map = {}
321 for i, commit in enumerate(self.rorepo.iter_commits('0.1.6', max_count=2)):
322 diff_item = commit
323 if i % 2 == 0:
324 diff_item = commit.tree
325 # END use tree every second item
326
327 for other in (None, NULL_TREE, commit.Index, commit.parents[0]):
328 for paths in (None, "CHANGES", ("CHANGES", "lib")):
329 for create_patch in range(2):
330 diff_index = diff_item.diff(other=other, paths=paths, create_patch=create_patch)
331 assert isinstance(diff_index, DiffIndex)
332
333 if diff_index:
334 self._assert_diff_format(diff_index)
335 for ct in DiffIndex.change_type:
336 key = 'ct_%s' % ct
337 assertion_map.setdefault(key, 0)
338 assertion_map[key] = assertion_map[key] + len(list(diff_index.iter_change_type(ct)))
339 # END for each changetype
340
341 # check entries
342 diff_set = set()
343 diff_set.add(diff_index[0])
344 diff_set.add(diff_index[0])
345 self.assertEqual(len(diff_set), 1)
346 self.assertEqual(diff_index[0], diff_index[0])
347 self.assertFalse(diff_index[0] != diff_index[0])
348
349 for dr in diff_index:
350 self.assertIsNotNone(str(dr), "Diff to string conversion should be possible")
351 # END diff index checking
352 # END for each patch option
353 # END for each path option
354 # END for each other side
355 # END for each commit
356
357 # assert we could always find at least one instance of the members we
358 # can iterate in the diff index - if not this indicates its not working correctly
359 # or our test does not span the whole range of possibilities
360 for key, value in assertion_map.items():
361 self.assertIsNotNone(value, "Did not find diff for %s" % key)
362 # END for each iteration type
363
364 # test path not existing in the index - should be ignored
365 c = self.rorepo.head.commit
366 cp = c.parents[0]
367 diff_index = c.diff(cp, ["does/not/exist"])
368 self.assertEqual(len(diff_index), 0)
+0
-493
git/test/test_docs.py less more
0 # -*- coding: utf-8 -*-
1 # test_git.py
2 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
3 #
4 # This module is part of GitPython and is released under
5 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
6 import os
7
8 from git.test.lib import TestBase
9 from git.test.lib.helper import with_rw_directory
10
11 import os.path
12
13
14 class Tutorials(TestBase):
15
16 def tearDown(self):
17 import gc
18 gc.collect()
19
20 # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, ## ACTUALLY skipped by `git.submodule.base#L869`.
21 # "FIXME: helper.wrapper fails with: PermissionError: [WinError 5] Access is denied: "
22 # "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\test_work_tree_unsupportedryfa60di\\master_repo\\.git\\objects\\pack\\pack-bc9e0787aef9f69e1591ef38ea0a6f566ec66fe3.idx") # noqa E501
23 @with_rw_directory
24 def test_init_repo_object(self, rw_dir):
25 # [1-test_init_repo_object]
26 from git import Repo
27
28 # rorepo is a Repo instance pointing to the git-python repository.
29 # For all you know, the first argument to Repo is a path to the repository
30 # you want to work with
31 repo = Repo(self.rorepo.working_tree_dir)
32 assert not repo.bare
33 # ![1-test_init_repo_object]
34
35 # [2-test_init_repo_object]
36 bare_repo = Repo.init(os.path.join(rw_dir, 'bare-repo'), bare=True)
37 assert bare_repo.bare
38 # ![2-test_init_repo_object]
39
40 # [3-test_init_repo_object]
41 repo.config_reader() # get a config reader for read-only access
42 with repo.config_writer(): # get a config writer to change configuration
43 pass # call release() to be sure changes are written and locks are released
44 # ![3-test_init_repo_object]
45
46 # [4-test_init_repo_object]
47 assert not bare_repo.is_dirty() # check the dirty state
48 repo.untracked_files # retrieve a list of untracked files
49 # ['my_untracked_file']
50 # ![4-test_init_repo_object]
51
52 # [5-test_init_repo_object]
53 cloned_repo = repo.clone(os.path.join(rw_dir, 'to/this/path'))
54 assert cloned_repo.__class__ is Repo # clone an existing repository
55 assert Repo.init(os.path.join(rw_dir, 'path/for/new/repo')).__class__ is Repo
56 # ![5-test_init_repo_object]
57
58 # [6-test_init_repo_object]
59 with open(os.path.join(rw_dir, 'repo.tar'), 'wb') as fp:
60 repo.archive(fp)
61 # ![6-test_init_repo_object]
62
63 # repository paths
64 # [7-test_init_repo_object]
65 assert os.path.isdir(cloned_repo.working_tree_dir) # directory with your work files
66 assert cloned_repo.git_dir.startswith(cloned_repo.working_tree_dir) # directory containing the git repository
67 assert bare_repo.working_tree_dir is None # bare repositories have no working tree
68 # ![7-test_init_repo_object]
69
70 # heads, tags and references
71 # heads are branches in git-speak
72 # [8-test_init_repo_object]
73 self.assertEqual(repo.head.ref, repo.heads.master, # head is a sym-ref pointing to master
74 "It's ok if TC not running from `master`.")
75 self.assertEqual(repo.tags['0.3.5'], repo.tag('refs/tags/0.3.5')) # you can access tags in various ways too
76 self.assertEqual(repo.refs.master, repo.heads['master']) # .refs provides all refs, ie heads ...
77
78 if 'TRAVIS' not in os.environ:
79 self.assertEqual(repo.refs['origin/master'], repo.remotes.origin.refs.master) # ... remotes ...
80 self.assertEqual(repo.refs['0.3.5'], repo.tags['0.3.5']) # ... and tags
81 # ![8-test_init_repo_object]
82
83 # create a new head/branch
84 # [9-test_init_repo_object]
85 new_branch = cloned_repo.create_head('feature') # create a new branch ...
86 assert cloned_repo.active_branch != new_branch # which wasn't checked out yet ...
87 self.assertEqual(new_branch.commit, cloned_repo.active_branch.commit) # pointing to the checked-out commit
88 # It's easy to let a branch point to the previous commit, without affecting anything else
89 # Each reference provides access to the git object it points to, usually commits
90 assert new_branch.set_commit('HEAD~1').commit == cloned_repo.active_branch.commit.parents[0]
91 # ![9-test_init_repo_object]
92
93 # create a new tag reference
94 # [10-test_init_repo_object]
95 past = cloned_repo.create_tag('past', ref=new_branch,
96 message="This is a tag-object pointing to %s" % new_branch.name)
97 self.assertEqual(past.commit, new_branch.commit) # the tag points to the specified commit
98 assert past.tag.message.startswith("This is") # and its object carries the message provided
99
100 now = cloned_repo.create_tag('now') # This is a tag-reference. It may not carry meta-data
101 assert now.tag is None
102 # ![10-test_init_repo_object]
103
104 # Object handling
105 # [11-test_init_repo_object]
106 assert now.commit.message != past.commit.message
107 # You can read objects directly through binary streams, no working tree required
108 assert (now.commit.tree / 'VERSION').data_stream.read().decode('ascii').startswith('3')
109
110 # You can traverse trees as well to handle all contained files of a particular commit
111 file_count = 0
112 tree_count = 0
113 tree = past.commit.tree
114 for item in tree.traverse():
115 file_count += item.type == 'blob'
116 tree_count += item.type == 'tree'
117 assert file_count and tree_count # we have accumulated all directories and files
118 self.assertEqual(len(tree.blobs) + len(tree.trees), len(tree)) # a tree is iterable on its children
119 # ![11-test_init_repo_object]
120
121 # remotes allow handling push, pull and fetch operations
122 # [12-test_init_repo_object]
123 from git import RemoteProgress
124
125 class MyProgressPrinter(RemoteProgress):
126 def update(self, op_code, cur_count, max_count=None, message=''):
127 print(op_code, cur_count, max_count, cur_count / (max_count or 100.0), message or "NO MESSAGE")
128 # end
129
130 self.assertEqual(len(cloned_repo.remotes), 1) # we have been cloned, so should be one remote
131 self.assertEqual(len(bare_repo.remotes), 0) # this one was just initialized
132 origin = bare_repo.create_remote('origin', url=cloned_repo.working_tree_dir)
133 assert origin.exists()
134 for fetch_info in origin.fetch(progress=MyProgressPrinter()):
135 print("Updated %s to %s" % (fetch_info.ref, fetch_info.commit))
136 # create a local branch at the latest fetched master. We specify the name statically, but you have all
137 # information to do it programatically as well.
138 bare_master = bare_repo.create_head('master', origin.refs.master)
139 bare_repo.head.set_reference(bare_master)
140 assert not bare_repo.delete_remote(origin).exists()
141 # push and pull behave very similarly
142 # ![12-test_init_repo_object]
143
144 # index
145 # [13-test_init_repo_object]
146 self.assertEqual(new_branch.checkout(), cloned_repo.active_branch) # checking out branch adjusts the wtree
147 self.assertEqual(new_branch.commit, past.commit) # Now the past is checked out
148
149 new_file_path = os.path.join(cloned_repo.working_tree_dir, 'my-new-file')
150 open(new_file_path, 'wb').close() # create new file in working tree
151 cloned_repo.index.add([new_file_path]) # add it to the index
152 # Commit the changes to deviate masters history
153 cloned_repo.index.commit("Added a new file in the past - for later merege")
154
155 # prepare a merge
156 master = cloned_repo.heads.master # right-hand side is ahead of us, in the future
157 merge_base = cloned_repo.merge_base(new_branch, master) # allwos for a three-way merge
158 cloned_repo.index.merge_tree(master, base=merge_base) # write the merge result into index
159 cloned_repo.index.commit("Merged past and now into future ;)",
160 parent_commits=(new_branch.commit, master.commit))
161
162 # now new_branch is ahead of master, which probably should be checked out and reset softly.
163 # note that all these operations didn't touch the working tree, as we managed it ourselves.
164 # This definitely requires you to know what you are doing :) !
165 assert os.path.basename(new_file_path) in new_branch.commit.tree # new file is now in tree
166 master.commit = new_branch.commit # let master point to most recent commit
167 cloned_repo.head.reference = master # we adjusted just the reference, not the working tree or index
168 # ![13-test_init_repo_object]
169
170 # submodules
171
172 # [14-test_init_repo_object]
173 # create a new submodule and check it out on the spot, setup to track master branch of `bare_repo`
174 # As our GitPython repository has submodules already that point to GitHub, make sure we don't
175 # interact with them
176 for sm in cloned_repo.submodules:
177 assert not sm.remove().exists() # after removal, the sm doesn't exist anymore
178 sm = cloned_repo.create_submodule('mysubrepo', 'path/to/subrepo', url=bare_repo.git_dir, branch='master')
179
180 # .gitmodules was written and added to the index, which is now being committed
181 cloned_repo.index.commit("Added submodule")
182 assert sm.exists() and sm.module_exists() # this submodule is defintely available
183 sm.remove(module=True, configuration=False) # remove the working tree
184 assert sm.exists() and not sm.module_exists() # the submodule itself is still available
185
186 # update all submodules, non-recursively to save time, this method is very powerful, go have a look
187 cloned_repo.submodule_update(recursive=False)
188 assert sm.module_exists() # The submodules working tree was checked out by update
189 # ![14-test_init_repo_object]
190
191 @with_rw_directory
192 def test_references_and_objects(self, rw_dir):
193 # [1-test_references_and_objects]
194 import git
195 repo = git.Repo.clone_from(self._small_repo_url(), os.path.join(rw_dir, 'repo'), branch='master')
196
197 heads = repo.heads
198 master = heads.master # lists can be accessed by name for convenience
199 master.commit # the commit pointed to by head called master
200 master.rename('new_name') # rename heads
201 master.rename('master')
202 # ![1-test_references_and_objects]
203
204 # [2-test_references_and_objects]
205 tags = repo.tags
206 tagref = tags[0]
207 tagref.tag # tags may have tag objects carrying additional information
208 tagref.commit # but they always point to commits
209 repo.delete_tag(tagref) # delete or
210 repo.create_tag("my_tag") # create tags using the repo for convenience
211 # ![2-test_references_and_objects]
212
213 # [3-test_references_and_objects]
214 head = repo.head # the head points to the active branch/ref
215 master = head.reference # retrieve the reference the head points to
216 master.commit # from here you use it as any other reference
217 # ![3-test_references_and_objects]
218 #
219 # [4-test_references_and_objects]
220 log = master.log()
221 log[0] # first (i.e. oldest) reflog entry
222 log[-1] # last (i.e. most recent) reflog entry
223 # ![4-test_references_and_objects]
224
225 # [5-test_references_and_objects]
226 new_branch = repo.create_head('new') # create a new one
227 new_branch.commit = 'HEAD~10' # set branch to another commit without changing index or working trees
228 repo.delete_head(new_branch) # delete an existing head - only works if it is not checked out
229 # ![5-test_references_and_objects]
230
231 # [6-test_references_and_objects]
232 new_tag = repo.create_tag('my_new_tag', message='my message')
233 # You cannot change the commit a tag points to. Tags need to be re-created
234 self.assertRaises(AttributeError, setattr, new_tag, 'commit', repo.commit('HEAD~1'))
235 repo.delete_tag(new_tag)
236 # ![6-test_references_and_objects]
237
238 # [7-test_references_and_objects]
239 new_branch = repo.create_head('another-branch')
240 repo.head.reference = new_branch
241 # ![7-test_references_and_objects]
242
243 # [8-test_references_and_objects]
244 hc = repo.head.commit
245 hct = hc.tree
246 hc != hct # @NoEffect
247 hc != repo.tags[0] # @NoEffect
248 hc == repo.head.reference.commit # @NoEffect
249 # ![8-test_references_and_objects]
250
251 # [9-test_references_and_objects]
252 self.assertEqual(hct.type, 'tree') # preset string type, being a class attribute
253 assert hct.size > 0 # size in bytes
254 assert len(hct.hexsha) == 40
255 assert len(hct.binsha) == 20
256 # ![9-test_references_and_objects]
257
258 # [10-test_references_and_objects]
259 self.assertEqual(hct.path, '') # root tree has no path
260 assert hct.trees[0].path != '' # the first contained item has one though
261 self.assertEqual(hct.mode, 0o40000) # trees have the mode of a linux directory
262 self.assertEqual(hct.blobs[0].mode, 0o100644) # blobs have specific mode, comparable to a standard linux fs
263 # ![10-test_references_and_objects]
264
265 # [11-test_references_and_objects]
266 hct.blobs[0].data_stream.read() # stream object to read data from
267 hct.blobs[0].stream_data(open(os.path.join(rw_dir, 'blob_data'), 'wb')) # write data to given stream
268 # ![11-test_references_and_objects]
269
270 # [12-test_references_and_objects]
271 repo.commit('master')
272 repo.commit('v0.8.1')
273 repo.commit('HEAD~10')
274 # ![12-test_references_and_objects]
275
276 # [13-test_references_and_objects]
277 fifty_first_commits = list(repo.iter_commits('master', max_count=50))
278 assert len(fifty_first_commits) == 50
279 # this will return commits 21-30 from the commit list as traversed backwards master
280 ten_commits_past_twenty = list(repo.iter_commits('master', max_count=10, skip=20))
281 assert len(ten_commits_past_twenty) == 10
282 assert fifty_first_commits[20:30] == ten_commits_past_twenty
283 # ![13-test_references_and_objects]
284
285 # [14-test_references_and_objects]
286 headcommit = repo.head.commit
287 assert len(headcommit.hexsha) == 40
288 assert len(headcommit.parents) > 0
289 assert headcommit.tree.type == 'tree'
290 assert len(headcommit.author.name) != 0
291 assert isinstance(headcommit.authored_date, int)
292 assert len(headcommit.committer.name) != 0
293 assert isinstance(headcommit.committed_date, int)
294 assert headcommit.message != ''
295 # ![14-test_references_and_objects]
296
297 # [15-test_references_and_objects]
298 import time
299 time.asctime(time.gmtime(headcommit.committed_date))
300 time.strftime("%a, %d %b %Y %H:%M", time.gmtime(headcommit.committed_date))
301 # ![15-test_references_and_objects]
302
303 # [16-test_references_and_objects]
304 assert headcommit.parents[0].parents[0].parents[0] == repo.commit('master^^^')
305 # ![16-test_references_and_objects]
306
307 # [17-test_references_and_objects]
308 tree = repo.heads.master.commit.tree
309 assert len(tree.hexsha) == 40
310 # ![17-test_references_and_objects]
311
312 # [18-test_references_and_objects]
313 assert len(tree.trees) > 0 # trees are subdirectories
314 assert len(tree.blobs) > 0 # blobs are files
315 assert len(tree.blobs) + len(tree.trees) == len(tree)
316 # ![18-test_references_and_objects]
317
318 # [19-test_references_and_objects]
319 self.assertEqual(tree['smmap'], tree / 'smmap') # access by index and by sub-path
320 for entry in tree: # intuitive iteration of tree members
321 print(entry)
322 blob = tree.trees[1].blobs[0] # let's get a blob in a sub-tree
323 assert blob.name
324 assert len(blob.path) < len(blob.abspath)
325 self.assertEqual(tree.trees[1].name + '/' + blob.name, blob.path) # this is how relative blob path generated
326 self.assertEqual(tree[blob.path], blob) # you can use paths like 'dir/file' in tree
327 # ![19-test_references_and_objects]
328
329 # [20-test_references_and_objects]
330 assert tree / 'smmap' == tree['smmap']
331 assert tree / blob.path == tree[blob.path]
332 # ![20-test_references_and_objects]
333
334 # [21-test_references_and_objects]
335 # This example shows the various types of allowed ref-specs
336 assert repo.tree() == repo.head.commit.tree
337 past = repo.commit('HEAD~5')
338 assert repo.tree(past) == repo.tree(past.hexsha)
339 self.assertEqual(repo.tree('v0.8.1').type, 'tree') # yes, you can provide any refspec - works everywhere
340 # ![21-test_references_and_objects]
341
342 # [22-test_references_and_objects]
343 assert len(tree) < len(list(tree.traverse()))
344 # ![22-test_references_and_objects]
345
346 # [23-test_references_and_objects]
347 index = repo.index
348 # The index contains all blobs in a flat list
349 assert len(list(index.iter_blobs())) == len([o for o in repo.head.commit.tree.traverse() if o.type == 'blob'])
350 # Access blob objects
351 for (_path, _stage), entry in index.entries.items():
352 pass
353 new_file_path = os.path.join(repo.working_tree_dir, 'new-file-name')
354 open(new_file_path, 'w').close()
355 index.add([new_file_path]) # add a new file to the index
356 index.remove(['LICENSE']) # remove an existing one
357 assert os.path.isfile(os.path.join(repo.working_tree_dir, 'LICENSE')) # working tree is untouched
358
359 self.assertEqual(index.commit("my commit message").type, 'commit') # commit changed index
360 repo.active_branch.commit = repo.commit('HEAD~1') # forget last commit
361
362 from git import Actor
363 author = Actor("An author", "author@example.com")
364 committer = Actor("A committer", "committer@example.com")
365 # commit by commit message and author and committer
366 index.commit("my commit message", author=author, committer=committer)
367 # ![23-test_references_and_objects]
368
369 # [24-test_references_and_objects]
370 from git import IndexFile
371 # loads a tree into a temporary index, which exists just in memory
372 IndexFile.from_tree(repo, 'HEAD~1')
373 # merge two trees three-way into memory
374 merge_index = IndexFile.from_tree(repo, 'HEAD~10', 'HEAD', repo.merge_base('HEAD~10', 'HEAD'))
375 # and persist it
376 merge_index.write(os.path.join(rw_dir, 'merged_index'))
377 # ![24-test_references_and_objects]
378
379 # [25-test_references_and_objects]
380 empty_repo = git.Repo.init(os.path.join(rw_dir, 'empty'))
381 origin = empty_repo.create_remote('origin', repo.remotes.origin.url)
382 assert origin.exists()
383 assert origin == empty_repo.remotes.origin == empty_repo.remotes['origin']
384 origin.fetch() # assure we actually have data. fetch() returns useful information
385 # Setup a local tracking branch of a remote branch
386 empty_repo.create_head('master', origin.refs.master) # create local branch "master" from remote "master"
387 empty_repo.heads.master.set_tracking_branch(origin.refs.master) # set local "master" to track remote "master
388 empty_repo.heads.master.checkout() # checkout local "master" to working tree
389 # Three above commands in one:
390 empty_repo.create_head('master', origin.refs.master).set_tracking_branch(origin.refs.master).checkout()
391 # rename remotes
392 origin.rename('new_origin')
393 # push and pull behaves similarly to `git push|pull`
394 origin.pull()
395 origin.push()
396 # assert not empty_repo.delete_remote(origin).exists() # create and delete remotes
397 # ![25-test_references_and_objects]
398
399 # [26-test_references_and_objects]
400 assert origin.url == repo.remotes.origin.url
401 with origin.config_writer as cw:
402 cw.set("pushurl", "other_url")
403
404 # Please note that in python 2, writing origin.config_writer.set(...) is totally safe.
405 # In py3 __del__ calls can be delayed, thus not writing changes in time.
406 # ![26-test_references_and_objects]
407
408 # [27-test_references_and_objects]
409 hcommit = repo.head.commit
410 hcommit.diff() # diff tree against index
411 hcommit.diff('HEAD~1') # diff tree against previous tree
412 hcommit.diff(None) # diff tree against working tree
413
414 index = repo.index
415 index.diff() # diff index against itself yielding empty diff
416 index.diff(None) # diff index against working copy
417 index.diff('HEAD') # diff index against current HEAD tree
418 # ![27-test_references_and_objects]
419
420 # [28-test_references_and_objects]
421 # Traverse added Diff objects only
422 for diff_added in hcommit.diff('HEAD~1').iter_change_type('A'):
423 print(diff_added)
424 # ![28-test_references_and_objects]
425
426 # [29-test_references_and_objects]
427 # Reset our working tree 10 commits into the past
428 past_branch = repo.create_head('past_branch', 'HEAD~10')
429 repo.head.reference = past_branch
430 assert not repo.head.is_detached
431 # reset the index and working tree to match the pointed-to commit
432 repo.head.reset(index=True, working_tree=True)
433
434 # To detach your head, you have to point to a commit directly
435 repo.head.reference = repo.commit('HEAD~5')
436 assert repo.head.is_detached
437 # now our head points 15 commits into the past, whereas the working tree
438 # and index are 10 commits in the past
439 # ![29-test_references_and_objects]
440
441 # [30-test_references_and_objects]
442 # checkout the branch using git-checkout. It will fail as the working tree appears dirty
443 self.assertRaises(git.GitCommandError, repo.heads.master.checkout)
444 repo.heads.past_branch.checkout()
445 # ![30-test_references_and_objects]
446
447 # [31-test_references_and_objects]
448 git = repo.git
449 git.checkout('HEAD', b="my_new_branch") # create a new branch
450 git.branch('another-new-one')
451 git.branch('-D', 'another-new-one') # pass strings for full control over argument order
452 git.for_each_ref() # '-' becomes '_' when calling it
453 # ![31-test_references_and_objects]
454
455 repo.git.clear_cache()
456
457 def test_submodules(self):
458 # [1-test_submodules]
459 repo = self.rorepo
460 sms = repo.submodules
461
462 assert len(sms) == 1
463 sm = sms[0]
464 self.assertEqual(sm.name, 'gitdb') # git-python has gitdb as single submodule ...
465 self.assertEqual(sm.children()[0].name, 'smmap') # ... which has smmap as single submodule
466
467 # The module is the repository referenced by the submodule
468 assert sm.module_exists() # the module is available, which doesn't have to be the case.
469 assert sm.module().working_tree_dir.endswith('gitdb')
470 # the submodule's absolute path is the module's path
471 assert sm.abspath == sm.module().working_tree_dir
472 self.assertEqual(len(sm.hexsha), 40) # Its sha defines the commit to checkout
473 assert sm.exists() # yes, this submodule is valid and exists
474 # read its configuration conveniently
475 assert sm.config_reader().get_value('path') == sm.path
476 self.assertEqual(len(sm.children()), 1) # query the submodule hierarchy
477 # ![1-test_submodules]
478
479 @with_rw_directory
480 def test_add_file_and_commit(self, rw_dir):
481 import git
482
483 repo_dir = os.path.join(rw_dir, 'my-new-repo')
484 file_name = os.path.join(repo_dir, 'new-file')
485
486 r = git.Repo.init(repo_dir)
487 # This function just creates an empty file ...
488 open(file_name, 'wb').close()
489 r.index.add([file_name])
490 r.index.commit("initial commit")
491
492 # ![test_add_file_and_commit]
+0
-169
git/test/test_exc.py less more
0 # -*- coding: utf-8 -*-
1 # test_exc.py
2 # Copyright (C) 2008, 2009, 2016 Michael Trier (mtrier@gmail.com) and contributors
3 #
4 # This module is part of GitPython and is released under
5 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
6
7
8 import re
9
10 import ddt
11 from git.exc import (
12 InvalidGitRepositoryError,
13 WorkTreeRepositoryUnsupported,
14 NoSuchPathError,
15 CommandError,
16 GitCommandNotFound,
17 GitCommandError,
18 CheckoutError,
19 CacheError,
20 UnmergedEntriesError,
21 HookExecutionError,
22 RepositoryDirtyError,
23 )
24 from git.test.lib import TestBase
25
26 import itertools as itt
27
28
29 _cmd_argvs = (
30 ('cmd', ),
31 ('θνιψοδε', ),
32 ('θνιψοδε', 'normal', 'argvs'),
33 ('cmd', 'ελληνικα', 'args'),
34 ('θνιψοδε', 'κι', 'αλλα', 'strange', 'args'),
35 ('θνιψοδε', 'κι', 'αλλα', 'non-unicode', 'args'),
36 )
37 _causes_n_substrings = (
38 (None, None), # noqa: E241 @IgnorePep8
39 (7, "exit code(7)"), # noqa: E241 @IgnorePep8
40 ('Some string', "'Some string'"), # noqa: E241 @IgnorePep8
41 ('παλιο string', "'παλιο string'"), # noqa: E241 @IgnorePep8
42 (Exception("An exc."), "Exception('An exc.')"), # noqa: E241 @IgnorePep8
43 (Exception("Κακια exc."), "Exception('Κακια exc.')"), # noqa: E241 @IgnorePep8
44 (object(), "<object object at "), # noqa: E241 @IgnorePep8
45 )
46
47 _streams_n_substrings = (None, 'steram', 'ομορφο stream', )
48
49
50 @ddt.ddt
51 class TExc(TestBase):
52
53 def test_ExceptionsHaveBaseClass(self):
54 from git.exc import GitError
55 self.assertIsInstance(GitError(), Exception)
56
57 exception_classes = [
58 InvalidGitRepositoryError,
59 WorkTreeRepositoryUnsupported,
60 NoSuchPathError,
61 CommandError,
62 GitCommandNotFound,
63 GitCommandError,
64 CheckoutError,
65 CacheError,
66 UnmergedEntriesError,
67 HookExecutionError,
68 RepositoryDirtyError,
69 ]
70 for ex_class in exception_classes:
71 self.assertTrue(issubclass(ex_class, GitError))
72
73 @ddt.data(*list(itt.product(_cmd_argvs, _causes_n_substrings, _streams_n_substrings)))
74 def test_CommandError_unicode(self, case):
75 argv, (cause, subs), stream = case
76 cls = CommandError
77 c = cls(argv, cause)
78 s = str(c)
79
80 self.assertIsNotNone(c._msg)
81 self.assertIn(' cmdline: ', s)
82
83 for a in argv:
84 self.assertIn(a, s)
85
86 if not cause:
87 self.assertIn("failed!", s)
88 else:
89 self.assertIn(" failed due to:", s)
90
91 if subs is not None:
92 # Substrings (must) already contain opening `'`.
93 subs = "(?<!')%s(?!')" % re.escape(subs)
94 self.assertRegex(s, subs)
95
96 if not stream:
97 c = cls(argv, cause)
98 s = str(c)
99 self.assertNotIn(" stdout:", s)
100 self.assertNotIn(" stderr:", s)
101 else:
102 c = cls(argv, cause, stream)
103 s = str(c)
104 self.assertIn(" stderr:", s)
105 self.assertIn(stream, s)
106
107 c = cls(argv, cause, None, stream)
108 s = str(c)
109 self.assertIn(" stdout:", s)
110 self.assertIn(stream, s)
111
112 c = cls(argv, cause, stream, stream + 'no2')
113 s = str(c)
114 self.assertIn(" stderr:", s)
115 self.assertIn(stream, s)
116 self.assertIn(" stdout:", s)
117 self.assertIn(stream + 'no2', s)
118
119 @ddt.data(
120 (['cmd1'], None),
121 (['cmd1'], "some cause"),
122 (['cmd1'], Exception()),
123 )
124 def test_GitCommandNotFound(self, init_args):
125 argv, cause = init_args
126 c = GitCommandNotFound(argv, cause)
127 s = str(c)
128
129 self.assertIn(argv[0], s)
130 if cause:
131 self.assertIn(' not found due to: ', s)
132 self.assertIn(str(cause), s)
133 else:
134 self.assertIn(' not found!', s)
135
136 @ddt.data(
137 (['cmd1'], None),
138 (['cmd1'], "some cause"),
139 (['cmd1'], Exception()),
140 )
141 def test_GitCommandError(self, init_args):
142 argv, cause = init_args
143 c = GitCommandError(argv, cause)
144 s = str(c)
145
146 self.assertIn(argv[0], s)
147 if cause:
148 self.assertIn(' failed due to: ', s)
149 self.assertIn(str(cause), s)
150 else:
151 self.assertIn(' failed!', s)
152
153 @ddt.data(
154 (['cmd1'], None),
155 (['cmd1'], "some cause"),
156 (['cmd1'], Exception()),
157 )
158 def test_HookExecutionError(self, init_args):
159 argv, cause = init_args
160 c = HookExecutionError(argv, cause)
161 s = str(c)
162
163 self.assertIn(argv[0], s)
164 if cause:
165 self.assertTrue(s.startswith('Hook('), s)
166 self.assertIn(str(cause), s)
167 else:
168 self.assertIn(' failed!', s)
+0
-285
git/test/test_fun.py less more
0 from io import BytesIO
1 from stat import S_IFDIR, S_IFREG, S_IFLNK
2 from os import stat
3 import os.path as osp
4 from unittest import SkipTest
5
6 from git import Git
7 from git.index import IndexFile
8 from git.index.fun import (
9 aggressive_tree_merge
10 )
11 from git.objects.fun import (
12 traverse_tree_recursive,
13 traverse_trees_recursive,
14 tree_to_stream,
15 tree_entries_from_data,
16 )
17 from git.repo.fun import (
18 find_worktree_git_dir
19 )
20 from git.test.lib import (
21 TestBase,
22 with_rw_repo,
23 with_rw_directory
24 )
25 from git.util import bin_to_hex, cygpath, join_path_native
26 from gitdb.base import IStream
27 from gitdb.typ import str_tree_type
28
29
30 class TestFun(TestBase):
31
32 def _assert_index_entries(self, entries, trees):
33 index = IndexFile.from_tree(self.rorepo, *[self.rorepo.tree(bin_to_hex(t).decode('ascii')) for t in trees])
34 assert entries
35 assert len(index.entries) == len(entries)
36 for entry in entries:
37 assert (entry.path, entry.stage) in index.entries
38 # END assert entry matches fully
39
40 def test_aggressive_tree_merge(self):
41 # head tree with additions, removals and modification compared to its predecessor
42 odb = self.rorepo.odb
43 HC = self.rorepo.commit("6c1faef799095f3990e9970bc2cb10aa0221cf9c")
44 H = HC.tree
45 B = HC.parents[0].tree
46
47 # entries from single tree
48 trees = [H.binsha]
49 self._assert_index_entries(aggressive_tree_merge(odb, trees), trees)
50
51 # from multiple trees
52 trees = [B.binsha, H.binsha]
53 self._assert_index_entries(aggressive_tree_merge(odb, trees), trees)
54
55 # three way, no conflict
56 tree = self.rorepo.tree
57 B = tree("35a09c0534e89b2d43ec4101a5fb54576b577905")
58 H = tree("4fe5cfa0e063a8d51a1eb6f014e2aaa994e5e7d4")
59 M = tree("1f2b19de3301e76ab3a6187a49c9c93ff78bafbd")
60 trees = [B.binsha, H.binsha, M.binsha]
61 self._assert_index_entries(aggressive_tree_merge(odb, trees), trees)
62
63 # three-way, conflict in at least one file, both modified
64 B = tree("a7a4388eeaa4b6b94192dce67257a34c4a6cbd26")
65 H = tree("f9cec00938d9059882bb8eabdaf2f775943e00e5")
66 M = tree("44a601a068f4f543f73fd9c49e264c931b1e1652")
67 trees = [B.binsha, H.binsha, M.binsha]
68 self._assert_index_entries(aggressive_tree_merge(odb, trees), trees)
69
70 # too many trees
71 self.assertRaises(ValueError, aggressive_tree_merge, odb, trees * 2)
72
73 def mktree(self, odb, entries):
74 """create a tree from the given tree entries and safe it to the database"""
75 sio = BytesIO()
76 tree_to_stream(entries, sio.write)
77 sio.seek(0)
78 istream = odb.store(IStream(str_tree_type, len(sio.getvalue()), sio))
79 return istream.binsha
80
81 @with_rw_repo('0.1.6')
82 def test_three_way_merge(self, rwrepo):
83 def mkfile(name, sha, executable=0):
84 return (sha, S_IFREG | 0o644 | executable * 0o111, name)
85
86 def mkcommit(name, sha):
87 return (sha, S_IFDIR | S_IFLNK, name)
88
89 def assert_entries(entries, num_entries, has_conflict=False):
90 assert len(entries) == num_entries
91 assert has_conflict == (len([e for e in entries if e.stage != 0]) > 0)
92 mktree = self.mktree
93
94 shaa = b"\1" * 20
95 shab = b"\2" * 20
96 shac = b"\3" * 20
97
98 odb = rwrepo.odb
99
100 # base tree
101 bfn = 'basefile'
102 fbase = mkfile(bfn, shaa)
103 tb = mktree(odb, [fbase])
104
105 # non-conflicting new files, same data
106 fa = mkfile('1', shab)
107 th = mktree(odb, [fbase, fa])
108 fb = mkfile('2', shac)
109 tm = mktree(odb, [fbase, fb])
110
111 # two new files, same base file
112 trees = [tb, th, tm]
113 assert_entries(aggressive_tree_merge(odb, trees), 3)
114
115 # both delete same file, add own one
116 fa = mkfile('1', shab)
117 th = mktree(odb, [fa])
118 fb = mkfile('2', shac)
119 tm = mktree(odb, [fb])
120
121 # two new files
122 trees = [tb, th, tm]
123 assert_entries(aggressive_tree_merge(odb, trees), 2)
124
125 # same file added in both, differently
126 fa = mkfile('1', shab)
127 th = mktree(odb, [fa])
128 fb = mkfile('1', shac)
129 tm = mktree(odb, [fb])
130
131 # expect conflict
132 trees = [tb, th, tm]
133 assert_entries(aggressive_tree_merge(odb, trees), 2, True)
134
135 # same file added, different mode
136 fa = mkfile('1', shab)
137 th = mktree(odb, [fa])
138 fb = mkcommit('1', shab)
139 tm = mktree(odb, [fb])
140
141 # expect conflict
142 trees = [tb, th, tm]
143 assert_entries(aggressive_tree_merge(odb, trees), 2, True)
144
145 # same file added in both
146 fa = mkfile('1', shab)
147 th = mktree(odb, [fa])
148 fb = mkfile('1', shab)
149 tm = mktree(odb, [fb])
150
151 # expect conflict
152 trees = [tb, th, tm]
153 assert_entries(aggressive_tree_merge(odb, trees), 1)
154
155 # modify same base file, differently
156 fa = mkfile(bfn, shab)
157 th = mktree(odb, [fa])
158 fb = mkfile(bfn, shac)
159 tm = mktree(odb, [fb])
160
161 # conflict, 3 versions on 3 stages
162 trees = [tb, th, tm]
163 assert_entries(aggressive_tree_merge(odb, trees), 3, True)
164
165 # change mode on same base file, by making one a commit, the other executable
166 # no content change ( this is totally unlikely to happen in the real world )
167 fa = mkcommit(bfn, shaa)
168 th = mktree(odb, [fa])
169 fb = mkfile(bfn, shaa, executable=1)
170 tm = mktree(odb, [fb])
171
172 # conflict, 3 versions on 3 stages, because of different mode
173 trees = [tb, th, tm]
174 assert_entries(aggressive_tree_merge(odb, trees), 3, True)
175
176 for is_them in range(2):
177 # only we/they change contents
178 fa = mkfile(bfn, shab)
179 th = mktree(odb, [fa])
180
181 trees = [tb, th, tb]
182 if is_them:
183 trees = [tb, tb, th]
184 entries = aggressive_tree_merge(odb, trees)
185 assert len(entries) == 1 and entries[0].binsha == shab
186
187 # only we/they change the mode
188 fa = mkcommit(bfn, shaa)
189 th = mktree(odb, [fa])
190
191 trees = [tb, th, tb]
192 if is_them:
193 trees = [tb, tb, th]
194 entries = aggressive_tree_merge(odb, trees)
195 assert len(entries) == 1 and entries[0].binsha == shaa and entries[0].mode == fa[1]
196
197 # one side deletes, the other changes = conflict
198 fa = mkfile(bfn, shab)
199 th = mktree(odb, [fa])
200 tm = mktree(odb, [])
201 trees = [tb, th, tm]
202 if is_them:
203 trees = [tb, tm, th]
204 # as one is deleted, there are only 2 entries
205 assert_entries(aggressive_tree_merge(odb, trees), 2, True)
206 # END handle ours, theirs
207
208 def _assert_tree_entries(self, entries, num_trees):
209 for entry in entries:
210 assert len(entry) == num_trees
211 paths = {e[2] for e in entry if e}
212
213 # only one path per set of entries
214 assert len(paths) == 1
215 # END verify entry
216
217 def test_tree_traversal(self):
218 # low level tree tarversal
219 odb = self.rorepo.odb
220 H = self.rorepo.tree('29eb123beb1c55e5db4aa652d843adccbd09ae18') # head tree
221 M = self.rorepo.tree('e14e3f143e7260de9581aee27e5a9b2645db72de') # merge tree
222 B = self.rorepo.tree('f606937a7a21237c866efafcad33675e6539c103') # base tree
223 B_old = self.rorepo.tree('1f66cfbbce58b4b552b041707a12d437cc5f400a') # old base tree
224
225 # two very different trees
226 entries = traverse_trees_recursive(odb, [B_old.binsha, H.binsha], '')
227 self._assert_tree_entries(entries, 2)
228
229 oentries = traverse_trees_recursive(odb, [H.binsha, B_old.binsha], '')
230 assert len(oentries) == len(entries)
231 self._assert_tree_entries(oentries, 2)
232
233 # single tree
234 is_no_tree = lambda i, d: i.type != 'tree'
235 entries = traverse_trees_recursive(odb, [B.binsha], '')
236 assert len(entries) == len(list(B.traverse(predicate=is_no_tree)))
237 self._assert_tree_entries(entries, 1)
238
239 # two trees
240 entries = traverse_trees_recursive(odb, [B.binsha, H.binsha], '')
241 self._assert_tree_entries(entries, 2)
242
243 # tree trees
244 entries = traverse_trees_recursive(odb, [B.binsha, H.binsha, M.binsha], '')
245 self._assert_tree_entries(entries, 3)
246
247 def test_tree_traversal_single(self):
248 max_count = 50
249 count = 0
250 odb = self.rorepo.odb
251 for commit in self.rorepo.commit("29eb123beb1c55e5db4aa652d843adccbd09ae18").traverse():
252 if count >= max_count:
253 break
254 count += 1
255 entries = traverse_tree_recursive(odb, commit.tree.binsha, '')
256 assert entries
257 # END for each commit
258
259 @with_rw_directory
260 def test_linked_worktree_traversal(self, rw_dir):
261 """Check that we can identify a linked worktree based on a .git file"""
262 git = Git(rw_dir)
263 if git.version_info[:3] < (2, 5, 1):
264 raise SkipTest("worktree feature unsupported")
265
266 rw_master = self.rorepo.clone(join_path_native(rw_dir, 'master_repo'))
267 branch = rw_master.create_head('aaaaaaaa')
268 worktree_path = join_path_native(rw_dir, 'worktree_repo')
269 if Git.is_cygwin():
270 worktree_path = cygpath(worktree_path)
271 rw_master.git.worktree('add', worktree_path, branch.name)
272
273 dotgit = osp.join(worktree_path, ".git")
274 statbuf = stat(dotgit)
275 self.assertTrue(statbuf.st_mode & S_IFREG)
276
277 gitdir = find_worktree_git_dir(dotgit)
278 self.assertIsNotNone(gitdir)
279 statbuf = stat(gitdir)
280 self.assertTrue(statbuf.st_mode & S_IFDIR)
281
282 def test_tree_entries_from_data_with_failing_name_decode_py3(self):
283 r = tree_entries_from_data(b'100644 \x9f\0aaa')
284 assert r == [(b'aaa', 33188, '\udc9f')], r
+0
-281
git/test/test_git.py less more
0 # -*- coding: utf-8 -*-
1 # test_git.py
2 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
3 #
4 # This module is part of GitPython and is released under
5 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
6 import os
7 import subprocess
8 import sys
9 from tempfile import TemporaryFile
10 from unittest import mock
11
12 from git import (
13 Git,
14 refresh,
15 GitCommandError,
16 GitCommandNotFound,
17 Repo,
18 cmd
19 )
20 from git.compat import is_darwin
21 from git.test.lib import (
22 TestBase,
23 fixture_path
24 )
25 from git.test.lib import with_rw_directory
26 from git.util import finalize_process
27
28 import os.path as osp
29
30 from git.compat import is_win
31
32
33 class TestGit(TestBase):
34
35 @classmethod
36 def setUpClass(cls):
37 super(TestGit, cls).setUpClass()
38 cls.git = Git(cls.rorepo.working_dir)
39
40 def tearDown(self):
41 import gc
42 gc.collect()
43
44 @mock.patch.object(Git, 'execute')
45 def test_call_process_calls_execute(self, git):
46 git.return_value = ''
47 self.git.version()
48 self.assertTrue(git.called)
49 self.assertEqual(git.call_args, ((['git', 'version'],), {}))
50
51 def test_call_unpack_args_unicode(self):
52 args = Git._Git__unpack_args('Unicode€™')
53 mangled_value = 'Unicode\u20ac\u2122'
54 self.assertEqual(args, [mangled_value])
55
56 def test_call_unpack_args(self):
57 args = Git._Git__unpack_args(['git', 'log', '--', 'Unicode€™'])
58 mangled_value = 'Unicode\u20ac\u2122'
59 self.assertEqual(args, ['git', 'log', '--', mangled_value])
60
61 def test_it_raises_errors(self):
62 self.assertRaises(GitCommandError, self.git.this_does_not_exist)
63
64 def test_it_transforms_kwargs_into_git_command_arguments(self):
65 self.assertEqual(["-s"], self.git.transform_kwargs(**{'s': True}))
66 self.assertEqual(["-s", "5"], self.git.transform_kwargs(**{'s': 5}))
67 self.assertEqual([], self.git.transform_kwargs(**{'s': None}))
68
69 self.assertEqual(["--max-count"], self.git.transform_kwargs(**{'max_count': True}))
70 self.assertEqual(["--max-count=5"], self.git.transform_kwargs(**{'max_count': 5}))
71 self.assertEqual(["--max-count=0"], self.git.transform_kwargs(**{'max_count': 0}))
72 self.assertEqual([], self.git.transform_kwargs(**{'max_count': None}))
73
74 # Multiple args are supported by using lists/tuples
75 self.assertEqual(["-L", "1-3", "-L", "12-18"], self.git.transform_kwargs(**{'L': ('1-3', '12-18')}))
76 self.assertEqual(["-C", "-C"], self.git.transform_kwargs(**{'C': [True, True, None, False]}))
77
78 # order is undefined
79 res = self.git.transform_kwargs(**{'s': True, 't': True})
80 self.assertEqual({'-s', '-t'}, set(res))
81
82 def test_it_executes_git_to_shell_and_returns_result(self):
83 self.assertRegex(self.git.execute(["git", "version"]), r'^git version [\d\.]{2}.*$')
84
85 def test_it_accepts_stdin(self):
86 filename = fixture_path("cat_file_blob")
87 with open(filename, 'r') as fh:
88 self.assertEqual("70c379b63ffa0795fdbfbc128e5a2818397b7ef8",
89 self.git.hash_object(istream=fh, stdin=True))
90
91 @mock.patch.object(Git, 'execute')
92 def test_it_ignores_false_kwargs(self, git):
93 # this_should_not_be_ignored=False implies it *should* be ignored
94 self.git.version(pass_this_kwarg=False)
95 self.assertTrue("pass_this_kwarg" not in git.call_args[1])
96
97 def test_it_raises_proper_exception_with_output_stream(self):
98 tmp_file = TemporaryFile()
99 self.assertRaises(GitCommandError, self.git.checkout, 'non-existent-branch', output_stream=tmp_file)
100
101 def test_it_accepts_environment_variables(self):
102 filename = fixture_path("ls_tree_empty")
103 with open(filename, 'r') as fh:
104 tree = self.git.mktree(istream=fh)
105 env = {
106 'GIT_AUTHOR_NAME': 'Author Name',
107 'GIT_AUTHOR_EMAIL': 'author@example.com',
108 'GIT_AUTHOR_DATE': '1400000000+0000',
109 'GIT_COMMITTER_NAME': 'Committer Name',
110 'GIT_COMMITTER_EMAIL': 'committer@example.com',
111 'GIT_COMMITTER_DATE': '1500000000+0000',
112 }
113 commit = self.git.commit_tree(tree, m='message', env=env)
114 self.assertEqual(commit, '4cfd6b0314682d5a58f80be39850bad1640e9241')
115
116 def test_persistent_cat_file_command(self):
117 # read header only
118 hexsha = "b2339455342180c7cc1e9bba3e9f181f7baa5167"
119 g = self.git.cat_file(
120 batch_check=True, istream=subprocess.PIPE, as_process=True
121 )
122 g.stdin.write(b"b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
123 g.stdin.flush()
124 obj_info = g.stdout.readline()
125
126 # read header + data
127 g = self.git.cat_file(
128 batch=True, istream=subprocess.PIPE, as_process=True
129 )
130 g.stdin.write(b"b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
131 g.stdin.flush()
132 obj_info_two = g.stdout.readline()
133 self.assertEqual(obj_info, obj_info_two)
134
135 # read data - have to read it in one large chunk
136 size = int(obj_info.split()[2])
137 g.stdout.read(size)
138 g.stdout.read(1)
139
140 # now we should be able to read a new object
141 g.stdin.write(b"b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
142 g.stdin.flush()
143 self.assertEqual(g.stdout.readline(), obj_info)
144
145 # same can be achieved using the respective command functions
146 hexsha, typename, size = self.git.get_object_header(hexsha)
147 hexsha, typename_two, size_two, _ = self.git.get_object_data(hexsha)
148 self.assertEqual(typename, typename_two)
149 self.assertEqual(size, size_two)
150
151 def test_version(self):
152 v = self.git.version_info
153 self.assertIsInstance(v, tuple)
154 for n in v:
155 self.assertIsInstance(n, int)
156 # END verify number types
157
158 def test_cmd_override(self):
159 prev_cmd = self.git.GIT_PYTHON_GIT_EXECUTABLE
160 exc = GitCommandNotFound
161 try:
162 # set it to something that doens't exist, assure it raises
163 type(self.git).GIT_PYTHON_GIT_EXECUTABLE = osp.join(
164 "some", "path", "which", "doesn't", "exist", "gitbinary")
165 self.assertRaises(exc, self.git.version)
166 finally:
167 type(self.git).GIT_PYTHON_GIT_EXECUTABLE = prev_cmd
168 # END undo adjustment
169
170 def test_refresh(self):
171 # test a bad git path refresh
172 self.assertRaises(GitCommandNotFound, refresh, "yada")
173
174 # test a good path refresh
175 which_cmd = "where" if is_win else "which"
176 path = os.popen("{0} git".format(which_cmd)).read().strip().split('\n')[0]
177 refresh(path)
178
179 def test_options_are_passed_to_git(self):
180 # This work because any command after git --version is ignored
181 git_version = self.git(version=True).NoOp()
182 git_command_version = self.git.version()
183 self.assertEqual(git_version, git_command_version)
184
185 def test_persistent_options(self):
186 git_command_version = self.git.version()
187 # analog to test_options_are_passed_to_git
188 self.git.set_persistent_git_options(version=True)
189 git_version = self.git.NoOp()
190 self.assertEqual(git_version, git_command_version)
191 # subsequent calls keep this option:
192 git_version_2 = self.git.NoOp()
193 self.assertEqual(git_version_2, git_command_version)
194
195 # reset to empty:
196 self.git.set_persistent_git_options()
197 self.assertRaises(GitCommandError, self.git.NoOp)
198
199 def test_single_char_git_options_are_passed_to_git(self):
200 input_value = 'TestValue'
201 output_value = self.git(c='user.name=%s' % input_value).config('--get', 'user.name')
202 self.assertEqual(input_value, output_value)
203
204 def test_change_to_transform_kwargs_does_not_break_command_options(self):
205 self.git.log(n=1)
206
207 def test_insert_after_kwarg_raises(self):
208 # This isn't a complete add command, which doesn't matter here
209 self.assertRaises(ValueError, self.git.remote, 'add', insert_kwargs_after='foo')
210
211 def test_env_vars_passed_to_git(self):
212 editor = 'non_existent_editor'
213 with mock.patch.dict('os.environ', {'GIT_EDITOR': editor}): # @UndefinedVariable
214 self.assertEqual(self.git.var("GIT_EDITOR"), editor)
215
216 @with_rw_directory
217 def test_environment(self, rw_dir):
218 # sanity check
219 self.assertEqual(self.git.environment(), {})
220
221 # make sure the context manager works and cleans up after itself
222 with self.git.custom_environment(PWD='/tmp'):
223 self.assertEqual(self.git.environment(), {'PWD': '/tmp'})
224
225 self.assertEqual(self.git.environment(), {})
226
227 old_env = self.git.update_environment(VARKEY='VARVALUE')
228 # The returned dict can be used to revert the change, hence why it has
229 # an entry with value 'None'.
230 self.assertEqual(old_env, {'VARKEY': None})
231 self.assertEqual(self.git.environment(), {'VARKEY': 'VARVALUE'})
232
233 new_env = self.git.update_environment(**old_env)
234 self.assertEqual(new_env, {'VARKEY': 'VARVALUE'})
235 self.assertEqual(self.git.environment(), {})
236
237 path = osp.join(rw_dir, 'failing-script.sh')
238 with open(path, 'wt') as stream:
239 stream.write("#!/usr/bin/env sh\n"
240 "echo FOO\n")
241 os.chmod(path, 0o777)
242
243 rw_repo = Repo.init(osp.join(rw_dir, 'repo'))
244 remote = rw_repo.create_remote('ssh-origin', "ssh://git@server/foo")
245
246 with rw_repo.git.custom_environment(GIT_SSH=path):
247 try:
248 remote.fetch()
249 except GitCommandError as err:
250 if sys.version_info[0] < 3 and is_darwin:
251 self.assertIn('ssh-orig', str(err))
252 self.assertEqual(err.status, 128)
253 else:
254 self.assertIn('FOO', str(err))
255
256 def test_handle_process_output(self):
257 from git.cmd import handle_process_output
258
259 line_count = 5002
260 count = [None, 0, 0]
261
262 def counter_stdout(line):
263 count[1] += 1
264
265 def counter_stderr(line):
266 count[2] += 1
267
268 cmdline = [sys.executable, fixture_path('cat_file.py'), str(fixture_path('issue-301_stderr'))]
269 proc = subprocess.Popen(cmdline,
270 stdin=None,
271 stdout=subprocess.PIPE,
272 stderr=subprocess.PIPE,
273 shell=False,
274 creationflags=cmd.PROC_CREATIONFLAGS,
275 )
276
277 handle_process_output(proc, counter_stdout, counter_stderr, finalize_process)
278
279 self.assertEqual(count[1], line_count)
280 self.assertEqual(count[2], line_count)
+0
-934
git/test/test_index.py less more
0 # -*- coding: utf-8 -*-
1 # test_index.py
2 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
3 #
4 # This module is part of GitPython and is released under
5 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
6
7 from io import BytesIO
8 import os
9 from stat import (
10 S_ISLNK,
11 ST_MODE
12 )
13 import tempfile
14 from unittest import skipIf
15
16 from git import (
17 IndexFile,
18 Repo,
19 BlobFilter,
20 UnmergedEntriesError,
21 Tree,
22 Object,
23 Diff,
24 GitCommandError,
25 CheckoutError,
26 )
27 from git.compat import is_win
28 from git.exc import (
29 HookExecutionError,
30 InvalidGitRepositoryError
31 )
32 from git.index.fun import hook_path
33 from git.index.typ import (
34 BaseIndexEntry,
35 IndexEntry
36 )
37 from git.objects import Blob
38 from git.test.lib import (
39 TestBase,
40 fixture_path,
41 fixture,
42 with_rw_repo
43 )
44 from git.test.lib import with_rw_directory
45 from git.util import Actor, rmtree
46 from git.util import HIDE_WINDOWS_KNOWN_ERRORS, hex_to_bin
47 from gitdb.base import IStream
48
49 import os.path as osp
50 from git.cmd import Git
51
52 HOOKS_SHEBANG = "#!/usr/bin/env sh\n"
53
54
55 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, "TODO: fix hooks execution on Windows: #703")
56 def _make_hook(git_dir, name, content, make_exec=True):
57 """A helper to create a hook"""
58 hp = hook_path(name, git_dir)
59 hpd = osp.dirname(hp)
60 if not osp.isdir(hpd):
61 os.mkdir(hpd)
62 with open(hp, "wt") as fp:
63 fp.write(HOOKS_SHEBANG + content)
64 if make_exec:
65 os.chmod(hp, 0o744)
66 return hp
67
68
69 class TestIndex(TestBase):
70
71 def __init__(self, *args):
72 super(TestIndex, self).__init__(*args)
73 self._reset_progress()
74
75 def _assert_fprogress(self, entries):
76 self.assertEqual(len(entries), len(self._fprogress_map))
77 for _path, call_count in self._fprogress_map.items():
78 self.assertEqual(call_count, 2)
79 # END for each item in progress map
80 self._reset_progress()
81
82 def _fprogress(self, path, done, item):
83 self._fprogress_map.setdefault(path, 0)
84 curval = self._fprogress_map[path]
85 if curval == 0:
86 assert not done
87 if curval == 1:
88 assert done
89 self._fprogress_map[path] = curval + 1
90
91 def _fprogress_add(self, path, done, item):
92 """Called as progress func - we keep track of the proper
93 call order"""
94 assert item is not None
95 self._fprogress(path, done, item)
96
97 def _reset_progress(self):
98 # maps paths to the count of calls
99 self._fprogress_map = {}
100
101 def _assert_entries(self, entries):
102 for entry in entries:
103 assert isinstance(entry, BaseIndexEntry)
104 assert not osp.isabs(entry.path)
105 assert "\\" not in entry.path
106 # END for each entry
107
108 def test_index_file_base(self):
109 # read from file
110 index = IndexFile(self.rorepo, fixture_path("index"))
111 assert index.entries
112 assert index.version > 0
113
114 # test entry
115 entry = next(iter(index.entries.values()))
116 for attr in ("path", "ctime", "mtime", "dev", "inode", "mode", "uid",
117 "gid", "size", "binsha", "hexsha", "stage"):
118 getattr(entry, attr)
119 # END for each method
120
121 # test update
122 entries = index.entries
123 assert isinstance(index.update(), IndexFile)
124 assert entries is not index.entries
125
126 # test stage
127 index_merge = IndexFile(self.rorepo, fixture_path("index_merge"))
128 self.assertEqual(len(index_merge.entries), 106)
129 assert len([e for e in index_merge.entries.values() if e.stage != 0])
130
131 # write the data - it must match the original
132 tmpfile = tempfile.mktemp()
133 index_merge.write(tmpfile)
134 with open(tmpfile, 'rb') as fp:
135 self.assertEqual(fp.read(), fixture("index_merge"))
136 os.remove(tmpfile)
137
138 def _cmp_tree_index(self, tree, index):
139 # fail unless both objects contain the same paths and blobs
140 if isinstance(tree, str):
141 tree = self.rorepo.commit(tree).tree
142
143 blist = []
144 for blob in tree.traverse(predicate=lambda e, d: e.type == "blob", branch_first=False):
145 assert (blob.path, 0) in index.entries
146 blist.append(blob)
147 # END for each blob in tree
148 if len(blist) != len(index.entries):
149 iset = {k[0] for k in index.entries.keys()}
150 bset = {b.path for b in blist}
151 raise AssertionError("CMP Failed: Missing entries in index: %s, missing in tree: %s" %
152 (bset - iset, iset - bset))
153 # END assertion message
154
155 @with_rw_repo('0.1.6')
156 def test_index_lock_handling(self, rw_repo):
157 def add_bad_blob():
158 rw_repo.index.add([Blob(rw_repo, b'f' * 20, 'bad-permissions', 'foo')])
159
160 try:
161 ## 1st fail on purpose adding into index.
162 add_bad_blob()
163 except Exception as ex:
164 msg_py3 = "required argument is not an integer"
165 msg_py2 = "cannot convert argument to integer"
166 assert msg_py2 in str(ex) or msg_py3 in str(ex)
167
168 ## 2nd time should not fail due to stray lock file
169 try:
170 add_bad_blob()
171 except Exception as ex:
172 assert "index.lock' could not be obtained" not in str(ex)
173
174 @with_rw_repo('0.1.6')
175 def test_index_file_from_tree(self, rw_repo):
176 common_ancestor_sha = "5117c9c8a4d3af19a9958677e45cda9269de1541"
177 cur_sha = "4b43ca7ff72d5f535134241e7c797ddc9c7a3573"
178 other_sha = "39f85c4358b7346fee22169da9cad93901ea9eb9"
179
180 # simple index from tree
181 base_index = IndexFile.from_tree(rw_repo, common_ancestor_sha)
182 assert base_index.entries
183 self._cmp_tree_index(common_ancestor_sha, base_index)
184
185 # merge two trees - its like a fast-forward
186 two_way_index = IndexFile.from_tree(rw_repo, common_ancestor_sha, cur_sha)
187 assert two_way_index.entries
188 self._cmp_tree_index(cur_sha, two_way_index)
189
190 # merge three trees - here we have a merge conflict
191 three_way_index = IndexFile.from_tree(rw_repo, common_ancestor_sha, cur_sha, other_sha)
192 assert len([e for e in three_way_index.entries.values() if e.stage != 0])
193
194 # ITERATE BLOBS
195 merge_required = lambda t: t[0] != 0
196 merge_blobs = list(three_way_index.iter_blobs(merge_required))
197 assert merge_blobs
198 assert merge_blobs[0][0] in (1, 2, 3)
199 assert isinstance(merge_blobs[0][1], Blob)
200
201 # test BlobFilter
202 prefix = 'lib/git'
203 for _stage, blob in base_index.iter_blobs(BlobFilter([prefix])):
204 assert blob.path.startswith(prefix)
205
206 # writing a tree should fail with an unmerged index
207 self.assertRaises(UnmergedEntriesError, three_way_index.write_tree)
208
209 # removed unmerged entries
210 unmerged_blob_map = three_way_index.unmerged_blobs()
211 assert unmerged_blob_map
212
213 # pick the first blob at the first stage we find and use it as resolved version
214 three_way_index.resolve_blobs(line[0][1] for line in unmerged_blob_map.values())
215 tree = three_way_index.write_tree()
216 assert isinstance(tree, Tree)
217 num_blobs = 0
218 for blob in tree.traverse(predicate=lambda item, d: item.type == "blob"):
219 assert (blob.path, 0) in three_way_index.entries
220 num_blobs += 1
221 # END for each blob
222 self.assertEqual(num_blobs, len(three_way_index.entries))
223
224 @with_rw_repo('0.1.6')
225 def test_index_merge_tree(self, rw_repo):
226 # A bit out of place, but we need a different repo for this:
227 self.assertNotEqual(self.rorepo, rw_repo)
228 self.assertEqual(len({self.rorepo, self.rorepo, rw_repo, rw_repo}), 2)
229
230 # SINGLE TREE MERGE
231 # current index is at the (virtual) cur_commit
232 next_commit = "4c39f9da792792d4e73fc3a5effde66576ae128c"
233 parent_commit = rw_repo.head.commit.parents[0]
234 manifest_key = IndexFile.entry_key('MANIFEST.in', 0)
235 manifest_entry = rw_repo.index.entries[manifest_key]
236 rw_repo.index.merge_tree(next_commit)
237 # only one change should be recorded
238 assert manifest_entry.binsha != rw_repo.index.entries[manifest_key].binsha
239
240 rw_repo.index.reset(rw_repo.head)
241 self.assertEqual(rw_repo.index.entries[manifest_key].binsha, manifest_entry.binsha)
242
243 # FAKE MERGE
244 #############
245 # Add a change with a NULL sha that should conflict with next_commit. We
246 # pretend there was a change, but we do not even bother adding a proper
247 # sha for it ( which makes things faster of course )
248 manifest_fake_entry = BaseIndexEntry((manifest_entry[0], b"\0" * 20, 0, manifest_entry[3]))
249 # try write flag
250 self._assert_entries(rw_repo.index.add([manifest_fake_entry], write=False))
251 # add actually resolves the null-hex-sha for us as a feature, but we can
252 # edit the index manually
253 assert rw_repo.index.entries[manifest_key].binsha != Object.NULL_BIN_SHA
254 # must operate on the same index for this ! Its a bit problematic as
255 # it might confuse people
256 index = rw_repo.index
257 index.entries[manifest_key] = IndexEntry.from_base(manifest_fake_entry)
258 index.write()
259 self.assertEqual(rw_repo.index.entries[manifest_key].hexsha, Diff.NULL_HEX_SHA)
260
261 # write an unchanged index ( just for the fun of it )
262 rw_repo.index.write()
263
264 # a three way merge would result in a conflict and fails as the command will
265 # not overwrite any entries in our index and hence leave them unmerged. This is
266 # mainly a protection feature as the current index is not yet in a tree
267 self.assertRaises(GitCommandError, index.merge_tree, next_commit, base=parent_commit)
268
269 # the only way to get the merged entries is to safe the current index away into a tree,
270 # which is like a temporary commit for us. This fails as well as the NULL sha deos not
271 # have a corresponding object
272 # NOTE: missing_ok is not a kwarg anymore, missing_ok is always true
273 # self.assertRaises(GitCommandError, index.write_tree)
274
275 # if missing objects are okay, this would work though ( they are always okay now )
276 # As we can't read back the tree with NULL_SHA, we rather set it to something else
277 index.entries[manifest_key] = IndexEntry(manifest_entry[:1] + (hex_to_bin('f' * 40),) + manifest_entry[2:])
278 tree = index.write_tree()
279
280 # now make a proper three way merge with unmerged entries
281 unmerged_tree = IndexFile.from_tree(rw_repo, parent_commit, tree, next_commit)
282 unmerged_blobs = unmerged_tree.unmerged_blobs()
283 self.assertEqual(len(unmerged_blobs), 1)
284 self.assertEqual(list(unmerged_blobs.keys())[0], manifest_key[0])
285
286 @with_rw_repo('0.1.6')
287 def test_index_file_diffing(self, rw_repo):
288 # default Index instance points to our index
289 index = IndexFile(rw_repo)
290 assert index.path is not None
291 assert len(index.entries)
292
293 # write the file back
294 index.write()
295
296 # could sha it, or check stats
297
298 # test diff
299 # resetting the head will leave the index in a different state, and the
300 # diff will yield a few changes
301 cur_head_commit = rw_repo.head.reference.commit
302 rw_repo.head.reset('HEAD~6', index=True, working_tree=False)
303
304 # diff against same index is 0
305 diff = index.diff()
306 self.assertEqual(len(diff), 0)
307
308 # against HEAD as string, must be the same as it matches index
309 diff = index.diff('HEAD')
310 self.assertEqual(len(diff), 0)
311
312 # against previous head, there must be a difference
313 diff = index.diff(cur_head_commit)
314 assert len(diff)
315
316 # we reverse the result
317 adiff = index.diff(str(cur_head_commit), R=True)
318 odiff = index.diff(cur_head_commit, R=False) # now its not reversed anymore
319 assert adiff != odiff
320 self.assertEqual(odiff, diff) # both unreversed diffs against HEAD
321
322 # against working copy - its still at cur_commit
323 wdiff = index.diff(None)
324 assert wdiff != adiff
325 assert wdiff != odiff
326
327 # against something unusual
328 self.assertRaises(ValueError, index.diff, int)
329
330 # adjust the index to match an old revision
331 cur_branch = rw_repo.active_branch
332 cur_commit = cur_branch.commit
333 rev_head_parent = 'HEAD~1'
334 assert index.reset(rev_head_parent) is index
335
336 self.assertEqual(cur_branch, rw_repo.active_branch)
337 self.assertEqual(cur_commit, rw_repo.head.commit)
338
339 # there must be differences towards the working tree which is in the 'future'
340 assert index.diff(None)
341
342 # reset the working copy as well to current head,to pull 'back' as well
343 new_data = b"will be reverted"
344 file_path = osp.join(rw_repo.working_tree_dir, "CHANGES")
345 with open(file_path, "wb") as fp:
346 fp.write(new_data)
347 index.reset(rev_head_parent, working_tree=True)
348 assert not index.diff(None)
349 self.assertEqual(cur_branch, rw_repo.active_branch)
350 self.assertEqual(cur_commit, rw_repo.head.commit)
351 with open(file_path, 'rb') as fp:
352 assert fp.read() != new_data
353
354 # test full checkout
355 test_file = osp.join(rw_repo.working_tree_dir, "CHANGES")
356 with open(test_file, 'ab') as fd:
357 fd.write(b"some data")
358 rval = index.checkout(None, force=True, fprogress=self._fprogress)
359 assert 'CHANGES' in list(rval)
360 self._assert_fprogress([None])
361 assert osp.isfile(test_file)
362
363 os.remove(test_file)
364 rval = index.checkout(None, force=False, fprogress=self._fprogress)
365 assert 'CHANGES' in list(rval)
366 self._assert_fprogress([None])
367 assert osp.isfile(test_file)
368
369 # individual file
370 os.remove(test_file)
371 rval = index.checkout(test_file, fprogress=self._fprogress)
372 self.assertEqual(list(rval)[0], 'CHANGES')
373 self._assert_fprogress([test_file])
374 assert osp.exists(test_file)
375
376 # checking out non-existing file throws
377 self.assertRaises(CheckoutError, index.checkout, "doesnt_exist_ever.txt.that")
378 self.assertRaises(CheckoutError, index.checkout, paths=["doesnt/exist"])
379
380 # checkout file with modifications
381 append_data = b"hello"
382 with open(test_file, "ab") as fp:
383 fp.write(append_data)
384 try:
385 index.checkout(test_file)
386 except CheckoutError as e:
387 self.assertEqual(len(e.failed_files), 1)
388 self.assertEqual(e.failed_files[0], osp.basename(test_file))
389 self.assertEqual(len(e.failed_files), len(e.failed_reasons))
390 self.assertIsInstance(e.failed_reasons[0], str)
391 self.assertEqual(len(e.valid_files), 0)
392 with open(test_file, 'rb') as fd:
393 s = fd.read()
394 self.assertTrue(s.endswith(append_data), s)
395 else:
396 raise AssertionError("Exception CheckoutError not thrown")
397
398 # if we force it it should work
399 index.checkout(test_file, force=True)
400 assert not open(test_file, 'rb').read().endswith(append_data)
401
402 # checkout directory
403 rmtree(osp.join(rw_repo.working_tree_dir, "lib"))
404 rval = index.checkout('lib')
405 assert len(list(rval)) > 1
406
407 def _count_existing(self, repo, files):
408 """
409 Returns count of files that actually exist in the repository directory.
410 """
411 existing = 0
412 basedir = repo.working_tree_dir
413 for f in files:
414 existing += osp.isfile(osp.join(basedir, f))
415 # END for each deleted file
416 return existing
417 # END num existing helper
418
419 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and Git.is_cygwin(),
420 """FIXME: File "C:\\projects\\gitpython\\git\\test\\test_index.py", line 642, in test_index_mutation
421 self.assertEqual(fd.read(), link_target)
422 AssertionError: '!<symlink>\xff\xfe/\x00e\x00t\x00c\x00/\x00t\x00h\x00a\x00t\x00\x00\x00'
423 != '/etc/that'
424 """)
425 @with_rw_repo('0.1.6')
426 def test_index_mutation(self, rw_repo):
427 index = rw_repo.index
428 num_entries = len(index.entries)
429 cur_head = rw_repo.head
430
431 uname = "Thomas Müller"
432 umail = "sd@company.com"
433 with rw_repo.config_writer() as writer:
434 writer.set_value("user", "name", uname)
435 writer.set_value("user", "email", umail)
436 self.assertEqual(writer.get_value("user", "name"), uname)
437
438 # remove all of the files, provide a wild mix of paths, BaseIndexEntries,
439 # IndexEntries
440 def mixed_iterator():
441 count = 0
442 for entry in index.entries.values():
443 type_id = count % 4
444 if type_id == 0: # path
445 yield entry.path
446 elif type_id == 1: # blob
447 yield Blob(rw_repo, entry.binsha, entry.mode, entry.path)
448 elif type_id == 2: # BaseIndexEntry
449 yield BaseIndexEntry(entry[:4])
450 elif type_id == 3: # IndexEntry
451 yield entry
452 else:
453 raise AssertionError("Invalid Type")
454 count += 1
455 # END for each entry
456 # END mixed iterator
457 deleted_files = index.remove(mixed_iterator(), working_tree=False)
458 assert deleted_files
459 self.assertEqual(self._count_existing(rw_repo, deleted_files), len(deleted_files))
460 self.assertEqual(len(index.entries), 0)
461
462 # reset the index to undo our changes
463 index.reset()
464 self.assertEqual(len(index.entries), num_entries)
465
466 # remove with working copy
467 deleted_files = index.remove(mixed_iterator(), working_tree=True)
468 assert deleted_files
469 self.assertEqual(self._count_existing(rw_repo, deleted_files), 0)
470
471 # reset everything
472 index.reset(working_tree=True)
473 self.assertEqual(self._count_existing(rw_repo, deleted_files), len(deleted_files))
474
475 # invalid type
476 self.assertRaises(TypeError, index.remove, [1])
477
478 # absolute path
479 deleted_files = index.remove([osp.join(rw_repo.working_tree_dir, "lib")], r=True)
480 assert len(deleted_files) > 1
481 self.assertRaises(ValueError, index.remove, ["/doesnt/exists"])
482
483 # TEST COMMITTING
484 # commit changed index
485 cur_commit = cur_head.commit
486 commit_message = "commit default head by Frèderic Çaufl€"
487
488 new_commit = index.commit(commit_message, head=False)
489 assert cur_commit != new_commit
490 self.assertEqual(new_commit.author.name, uname)
491 self.assertEqual(new_commit.author.email, umail)
492 self.assertEqual(new_commit.committer.name, uname)
493 self.assertEqual(new_commit.committer.email, umail)
494 self.assertEqual(new_commit.message, commit_message)
495 self.assertEqual(new_commit.parents[0], cur_commit)
496 self.assertEqual(len(new_commit.parents), 1)
497 self.assertEqual(cur_head.commit, cur_commit)
498
499 # commit with other actor
500 cur_commit = cur_head.commit
501
502 my_author = Actor("Frèderic Çaufl€", "author@example.com")
503 my_committer = Actor("Committing Frèderic Çaufl€", "committer@example.com")
504 commit_actor = index.commit(commit_message, author=my_author, committer=my_committer)
505 assert cur_commit != commit_actor
506 self.assertEqual(commit_actor.author.name, "Frèderic Çaufl€")
507 self.assertEqual(commit_actor.author.email, "author@example.com")
508 self.assertEqual(commit_actor.committer.name, "Committing Frèderic Çaufl€")
509 self.assertEqual(commit_actor.committer.email, "committer@example.com")
510 self.assertEqual(commit_actor.message, commit_message)
511 self.assertEqual(commit_actor.parents[0], cur_commit)
512 self.assertEqual(len(new_commit.parents), 1)
513 self.assertEqual(cur_head.commit, commit_actor)
514 self.assertEqual(cur_head.log()[-1].actor, my_committer)
515
516 # commit with author_date and commit_date
517 cur_commit = cur_head.commit
518 commit_message = "commit with dates by Avinash Sajjanshetty"
519
520 new_commit = index.commit(commit_message, author_date="2006-04-07T22:13:13", commit_date="2005-04-07T22:13:13")
521 assert cur_commit != new_commit
522 print(new_commit.authored_date, new_commit.committed_date)
523 self.assertEqual(new_commit.message, commit_message)
524 self.assertEqual(new_commit.authored_date, 1144447993)
525 self.assertEqual(new_commit.committed_date, 1112911993)
526
527 # same index, no parents
528 commit_message = "index without parents"
529 commit_no_parents = index.commit(commit_message, parent_commits=[], head=True)
530 self.assertEqual(commit_no_parents.message, commit_message)
531 self.assertEqual(len(commit_no_parents.parents), 0)
532 self.assertEqual(cur_head.commit, commit_no_parents)
533
534 # same index, multiple parents
535 commit_message = "Index with multiple parents\n commit with another line"
536 commit_multi_parent = index.commit(commit_message, parent_commits=(commit_no_parents, new_commit))
537 self.assertEqual(commit_multi_parent.message, commit_message)
538 self.assertEqual(len(commit_multi_parent.parents), 2)
539 self.assertEqual(commit_multi_parent.parents[0], commit_no_parents)
540 self.assertEqual(commit_multi_parent.parents[1], new_commit)
541 self.assertEqual(cur_head.commit, commit_multi_parent)
542
543 # re-add all files in lib
544 # get the lib folder back on disk, but get an index without it
545 index.reset(new_commit.parents[0], working_tree=True).reset(new_commit, working_tree=False)
546 lib_file_path = osp.join("lib", "git", "__init__.py")
547 assert (lib_file_path, 0) not in index.entries
548 assert osp.isfile(osp.join(rw_repo.working_tree_dir, lib_file_path))
549
550 # directory
551 entries = index.add(['lib'], fprogress=self._fprogress_add)
552 self._assert_entries(entries)
553 self._assert_fprogress(entries)
554 assert len(entries) > 1
555
556 # glob
557 entries = index.reset(new_commit).add([osp.join('lib', 'git', '*.py')], fprogress=self._fprogress_add)
558 self._assert_entries(entries)
559 self._assert_fprogress(entries)
560 self.assertEqual(len(entries), 14)
561
562 # same file
563 entries = index.reset(new_commit).add(
564 [osp.join(rw_repo.working_tree_dir, 'lib', 'git', 'head.py')] * 2, fprogress=self._fprogress_add)
565 self._assert_entries(entries)
566 self.assertEqual(entries[0].mode & 0o644, 0o644)
567 # would fail, test is too primitive to handle this case
568 # self._assert_fprogress(entries)
569 self._reset_progress()
570 self.assertEqual(len(entries), 2)
571
572 # missing path
573 self.assertRaises(OSError, index.reset(new_commit).add, ['doesnt/exist/must/raise'])
574
575 # blob from older revision overrides current index revision
576 old_blob = new_commit.parents[0].tree.blobs[0]
577 entries = index.reset(new_commit).add([old_blob], fprogress=self._fprogress_add)
578 self._assert_entries(entries)
579 self._assert_fprogress(entries)
580 self.assertEqual(index.entries[(old_blob.path, 0)].hexsha, old_blob.hexsha)
581 self.assertEqual(len(entries), 1)
582
583 # mode 0 not allowed
584 null_hex_sha = Diff.NULL_HEX_SHA
585 null_bin_sha = b"\0" * 20
586 self.assertRaises(ValueError, index.reset(
587 new_commit).add, [BaseIndexEntry((0, null_bin_sha, 0, "doesntmatter"))])
588
589 # add new file
590 new_file_relapath = "my_new_file"
591 self._make_file(new_file_relapath, "hello world", rw_repo)
592 entries = index.reset(new_commit).add(
593 [BaseIndexEntry((0o10644, null_bin_sha, 0, new_file_relapath))], fprogress=self._fprogress_add)
594 self._assert_entries(entries)
595 self._assert_fprogress(entries)
596 self.assertEqual(len(entries), 1)
597 self.assertNotEqual(entries[0].hexsha, null_hex_sha)
598
599 # add symlink
600 if not is_win:
601 for target in ('/etc/nonexisting', '/etc/passwd', '/etc'):
602 basename = "my_real_symlink"
603
604 link_file = osp.join(rw_repo.working_tree_dir, basename)
605 os.symlink(target, link_file)
606 entries = index.reset(new_commit).add([link_file], fprogress=self._fprogress_add)
607 self._assert_entries(entries)
608 self._assert_fprogress(entries)
609 self.assertEqual(len(entries), 1)
610 self.assertTrue(S_ISLNK(entries[0].mode))
611 self.assertTrue(S_ISLNK(index.entries[index.entry_key("my_real_symlink", 0)].mode))
612
613 # we expect only the target to be written
614 self.assertEqual(index.repo.odb.stream(entries[0].binsha).read().decode('ascii'), target)
615
616 os.remove(link_file)
617 # end for each target
618 # END real symlink test
619
620 # add fake symlink and assure it checks-our as symlink
621 fake_symlink_relapath = "my_fake_symlink"
622 link_target = "/etc/that"
623 fake_symlink_path = self._make_file(fake_symlink_relapath, link_target, rw_repo)
624 fake_entry = BaseIndexEntry((0o120000, null_bin_sha, 0, fake_symlink_relapath))
625 entries = index.reset(new_commit).add([fake_entry], fprogress=self._fprogress_add)
626 self._assert_entries(entries)
627 self._assert_fprogress(entries)
628 assert entries[0].hexsha != null_hex_sha
629 self.assertEqual(len(entries), 1)
630 self.assertTrue(S_ISLNK(entries[0].mode))
631
632 # assure this also works with an alternate method
633 full_index_entry = IndexEntry.from_base(BaseIndexEntry((0o120000, entries[0].binsha, 0, entries[0].path)))
634 entry_key = index.entry_key(full_index_entry)
635 index.reset(new_commit)
636
637 assert entry_key not in index.entries
638 index.entries[entry_key] = full_index_entry
639 index.write()
640 index.update() # force reread of entries
641 new_entry = index.entries[entry_key]
642 assert S_ISLNK(new_entry.mode)
643
644 # a tree created from this should contain the symlink
645 tree = index.write_tree()
646 assert fake_symlink_relapath in tree
647 index.write() # flush our changes for the checkout
648
649 # checkout the fakelink, should be a link then
650 assert not S_ISLNK(os.stat(fake_symlink_path)[ST_MODE])
651 os.remove(fake_symlink_path)
652 index.checkout(fake_symlink_path)
653
654 # on windows we will never get symlinks
655 if is_win:
656 # simlinks should contain the link as text ( which is what a
657 # symlink actually is )
658 with open(fake_symlink_path, 'rt') as fd:
659 self.assertEqual(fd.read(), link_target)
660 else:
661 self.assertTrue(S_ISLNK(os.lstat(fake_symlink_path)[ST_MODE]))
662
663 # TEST RENAMING
664 def assert_mv_rval(rval):
665 for source, dest in rval:
666 assert not osp.exists(source) and osp.exists(dest)
667 # END for each renamed item
668 # END move assertion utility
669
670 self.assertRaises(ValueError, index.move, ['just_one_path'])
671 # file onto existing file
672 files = ['AUTHORS', 'LICENSE']
673 self.assertRaises(GitCommandError, index.move, files)
674
675 # again, with force
676 assert_mv_rval(index.move(files, f=True))
677
678 # files into directory - dry run
679 paths = ['LICENSE', 'VERSION', 'doc']
680 rval = index.move(paths, dry_run=True)
681 self.assertEqual(len(rval), 2)
682 assert osp.exists(paths[0])
683
684 # again, no dry run
685 rval = index.move(paths)
686 assert_mv_rval(rval)
687
688 # dir into dir
689 rval = index.move(['doc', 'test'])
690 assert_mv_rval(rval)
691
692 # TEST PATH REWRITING
693 ######################
694 count = [0]
695
696 def rewriter(entry):
697 rval = str(count[0])
698 count[0] += 1
699 return rval
700 # END rewriter
701
702 def make_paths():
703 # two existing ones, one new one
704 yield 'CHANGES'
705 yield 'ez_setup.py'
706 yield index.entries[index.entry_key('README', 0)]
707 yield index.entries[index.entry_key('.gitignore', 0)]
708
709 for fid in range(3):
710 fname = 'newfile%i' % fid
711 with open(fname, 'wb') as fd:
712 fd.write(b"abcd")
713 yield Blob(rw_repo, Blob.NULL_BIN_SHA, 0o100644, fname)
714 # END for each new file
715 # END path producer
716 paths = list(make_paths())
717 self._assert_entries(index.add(paths, path_rewriter=rewriter))
718
719 for filenum in range(len(paths)):
720 assert index.entry_key(str(filenum), 0) in index.entries
721
722 # TEST RESET ON PATHS
723 ######################
724 arela = "aa"
725 brela = "bb"
726 afile = self._make_file(arela, "adata", rw_repo)
727 bfile = self._make_file(brela, "bdata", rw_repo)
728 akey = index.entry_key(arela, 0)
729 bkey = index.entry_key(brela, 0)
730 keys = (akey, bkey)
731 absfiles = (afile, bfile)
732 files = (arela, brela)
733
734 for fkey in keys:
735 assert fkey not in index.entries
736
737 index.add(files, write=True)
738 nc = index.commit("2 files committed", head=False)
739
740 for fkey in keys:
741 assert fkey in index.entries
742
743 # just the index
744 index.reset(paths=(arela, afile))
745 assert akey not in index.entries
746 assert bkey in index.entries
747
748 # now with working tree - files on disk as well as entries must be recreated
749 rw_repo.head.commit = nc
750 for absfile in absfiles:
751 os.remove(absfile)
752
753 index.reset(working_tree=True, paths=files)
754
755 for fkey in keys:
756 assert fkey in index.entries
757 for absfile in absfiles:
758 assert osp.isfile(absfile)
759
760 @with_rw_repo('HEAD')
761 def test_compare_write_tree(self, rw_repo):
762 # write all trees and compare them
763 # its important to have a few submodules in there too
764 max_count = 25
765 count = 0
766 for commit in rw_repo.head.commit.traverse():
767 if count >= max_count:
768 break
769 count += 1
770 index = rw_repo.index.reset(commit)
771 orig_tree = commit.tree
772 self.assertEqual(index.write_tree(), orig_tree)
773 # END for each commit
774
775 @with_rw_repo('HEAD', bare=False)
776 def test_index_single_addremove(self, rw_repo):
777 fp = osp.join(rw_repo.working_dir, 'testfile.txt')
778 with open(fp, 'w') as fs:
779 fs.write('content of testfile')
780 self._assert_entries(rw_repo.index.add(fp))
781 deleted_files = rw_repo.index.remove(fp)
782 assert deleted_files
783
784 def test_index_new(self):
785 B = self.rorepo.tree("6d9b1f4f9fa8c9f030e3207e7deacc5d5f8bba4e")
786 H = self.rorepo.tree("25dca42bac17d511b7e2ebdd9d1d679e7626db5f")
787 M = self.rorepo.tree("e746f96bcc29238b79118123028ca170adc4ff0f")
788
789 for args in ((B,), (B, H), (B, H, M)):
790 index = IndexFile.new(self.rorepo, *args)
791 assert isinstance(index, IndexFile)
792 # END for each arg tuple
793
794 @with_rw_repo('HEAD', bare=True)
795 def test_index_bare_add(self, rw_bare_repo):
796 # Something is wrong after cloning to a bare repo, reading the
797 # property rw_bare_repo.working_tree_dir will return '/tmp'
798 # instead of throwing the Exception we are expecting. This is
799 # a quick hack to make this test fail when expected.
800 assert rw_bare_repo.working_tree_dir is None
801 assert rw_bare_repo.bare
802 contents = b'This is a BytesIO file'
803 filesize = len(contents)
804 fileobj = BytesIO(contents)
805 filename = 'my-imaginary-file'
806 istream = rw_bare_repo.odb.store(
807 IStream(Blob.type, filesize, fileobj))
808 entry = BaseIndexEntry((0o100644, istream.binsha, 0, filename))
809 try:
810 rw_bare_repo.index.add([entry])
811 except AssertionError:
812 self.fail("Adding to the index of a bare repo is not allowed.")
813
814 # Adding using a path should still require a non-bare repository.
815 asserted = False
816 path = osp.join('git', 'test', 'test_index.py')
817 try:
818 rw_bare_repo.index.add([path])
819 except InvalidGitRepositoryError:
820 asserted = True
821 assert asserted, "Adding using a filename is not correctly asserted."
822
823 @with_rw_directory
824 def test_add_utf8P_path(self, rw_dir):
825 # NOTE: fp is not a Unicode object in python 2 (which is the source of the problem)
826 fp = osp.join(rw_dir, 'ø.txt')
827 with open(fp, 'wb') as fs:
828 fs.write('content of ø'.encode('utf-8'))
829
830 r = Repo.init(rw_dir)
831 r.index.add([fp])
832 r.index.commit('Added orig and prestable')
833
834 @with_rw_directory
835 def test_add_a_file_with_wildcard_chars(self, rw_dir):
836 # see issue #407
837 fp = osp.join(rw_dir, '[.exe')
838 with open(fp, "wb") as f:
839 f.write(b'something')
840
841 r = Repo.init(rw_dir)
842 r.index.add([fp])
843 r.index.commit('Added [.exe')
844
845 def test__to_relative_path_at_root(self):
846 root = osp.abspath(os.sep)
847
848 class Mocked(object):
849 bare = False
850 git_dir = root
851 working_tree_dir = root
852
853 repo = Mocked()
854 path = os.path.join(root, 'file')
855 index = IndexFile(repo)
856
857 rel = index._to_relative_path(path)
858 self.assertEqual(rel, os.path.relpath(path, root))
859
860 @with_rw_repo('HEAD', bare=True)
861 def test_pre_commit_hook_success(self, rw_repo):
862 index = rw_repo.index
863 _make_hook(
864 index.repo.git_dir,
865 'pre-commit',
866 "exit 0"
867 )
868 index.commit("This should not fail")
869
870 @with_rw_repo('HEAD', bare=True)
871 def test_pre_commit_hook_fail(self, rw_repo):
872 index = rw_repo.index
873 hp = _make_hook(
874 index.repo.git_dir,
875 'pre-commit',
876 "echo stdout; echo stderr 1>&2; exit 1"
877 )
878 try:
879 index.commit("This should fail")
880 except HookExecutionError as err:
881 if is_win:
882 self.assertIsInstance(err.status, OSError)
883 self.assertEqual(err.command, [hp])
884 self.assertEqual(err.stdout, '')
885 self.assertEqual(err.stderr, '')
886 assert str(err)
887 else:
888 self.assertEqual(err.status, 1)
889 self.assertEqual(err.command, [hp])
890 self.assertEqual(err.stdout, "\n stdout: 'stdout\n'")
891 self.assertEqual(err.stderr, "\n stderr: 'stderr\n'")
892 assert str(err)
893 else:
894 raise AssertionError("Should have caught a HookExecutionError")
895
896 @with_rw_repo('HEAD', bare=True)
897 def test_commit_msg_hook_success(self, rw_repo):
898 commit_message = "commit default head by Frèderic Çaufl€"
899 from_hook_message = "from commit-msg"
900 index = rw_repo.index
901 _make_hook(
902 index.repo.git_dir,
903 'commit-msg',
904 'printf " {}" >> "$1"'.format(from_hook_message)
905 )
906 new_commit = index.commit(commit_message)
907 self.assertEqual(new_commit.message, "{} {}".format(commit_message, from_hook_message))
908
909 @with_rw_repo('HEAD', bare=True)
910 def test_commit_msg_hook_fail(self, rw_repo):
911 index = rw_repo.index
912 hp = _make_hook(
913 index.repo.git_dir,
914 'commit-msg',
915 "echo stdout; echo stderr 1>&2; exit 1"
916 )
917 try:
918 index.commit("This should fail")
919 except HookExecutionError as err:
920 if is_win:
921 self.assertIsInstance(err.status, OSError)
922 self.assertEqual(err.command, [hp])
923 self.assertEqual(err.stdout, '')
924 self.assertEqual(err.stderr, '')
925 assert str(err)
926 else:
927 self.assertEqual(err.status, 1)
928 self.assertEqual(err.command, [hp])
929 self.assertEqual(err.stdout, "\n stdout: 'stdout\n'")
930 self.assertEqual(err.stderr, "\n stderr: 'stderr\n'")
931 assert str(err)
932 else:
933 raise AssertionError("Should have cought a HookExecutionError")
+0
-107
git/test/test_reflog.py less more
0 import os
1 import tempfile
2
3 from git.objects import IndexObject
4 from git.refs import (
5 RefLogEntry,
6 RefLog
7 )
8 from git.test.lib import (
9 TestBase,
10 fixture_path
11 )
12 from git.util import Actor, rmtree, hex_to_bin
13
14 import os.path as osp
15
16
17 class TestRefLog(TestBase):
18
19 def test_reflogentry(self):
20 nullhexsha = IndexObject.NULL_HEX_SHA
21 hexsha = 'F' * 40
22 actor = Actor('name', 'email')
23 msg = "message"
24
25 self.assertRaises(ValueError, RefLogEntry.new, nullhexsha, hexsha, 'noactor', 0, 0, "")
26 e = RefLogEntry.new(nullhexsha, hexsha, actor, 0, 1, msg)
27
28 assert e.oldhexsha == nullhexsha
29 assert e.newhexsha == hexsha
30 assert e.actor == actor
31 assert e.time[0] == 0
32 assert e.time[1] == 1
33 assert e.message == msg
34
35 # check representation (roughly)
36 assert repr(e).startswith(nullhexsha)
37
38 def test_base(self):
39 rlp_head = fixture_path('reflog_HEAD')
40 rlp_master = fixture_path('reflog_master')
41 tdir = tempfile.mktemp(suffix="test_reflogs")
42 os.mkdir(tdir)
43
44 rlp_master_ro = RefLog.path(self.rorepo.head)
45 assert osp.isfile(rlp_master_ro)
46
47 # simple read
48 reflog = RefLog.from_file(rlp_master_ro)
49 assert reflog._path is not None
50 assert isinstance(reflog, RefLog)
51 assert len(reflog)
52
53 # iter_entries works with path and with stream
54 assert len(list(RefLog.iter_entries(open(rlp_master, 'rb'))))
55 assert len(list(RefLog.iter_entries(rlp_master)))
56
57 # raise on invalid revlog
58 # TODO: Try multiple corrupted ones !
59 pp = 'reflog_invalid_'
60 for suffix in ('oldsha', 'newsha', 'email', 'date', 'sep'):
61 self.assertRaises(ValueError, RefLog.from_file, fixture_path(pp + suffix))
62 # END for each invalid file
63
64 # cannot write an uninitialized reflog
65 self.assertRaises(ValueError, RefLog().write)
66
67 # test serialize and deserialize - results must match exactly
68 binsha = hex_to_bin(('f' * 40).encode('ascii'))
69 msg = "my reflog message"
70 cr = self.rorepo.config_reader()
71 for rlp in (rlp_head, rlp_master):
72 reflog = RefLog.from_file(rlp)
73 tfile = osp.join(tdir, osp.basename(rlp))
74 reflog.to_file(tfile)
75 assert reflog.write() is reflog
76
77 # parsed result must match ...
78 treflog = RefLog.from_file(tfile)
79 assert treflog == reflog
80
81 # ... as well as each bytes of the written stream
82 assert open(tfile).read() == open(rlp).read()
83
84 # append an entry
85 entry = RefLog.append_entry(cr, tfile, IndexObject.NULL_BIN_SHA, binsha, msg)
86 assert entry.oldhexsha == IndexObject.NULL_HEX_SHA
87 assert entry.newhexsha == 'f' * 40
88 assert entry.message == msg
89 assert RefLog.from_file(tfile)[-1] == entry
90
91 # index entry
92 # raises on invalid index
93 self.assertRaises(IndexError, RefLog.entry_at, rlp, 10000)
94
95 # indices can be positive ...
96 assert isinstance(RefLog.entry_at(rlp, 0), RefLogEntry)
97 RefLog.entry_at(rlp, 23)
98
99 # ... and negative
100 for idx in (-1, -24):
101 RefLog.entry_at(rlp, idx)
102 # END for each index to read
103 # END for each reflog
104
105 # finally remove our temporary data
106 rmtree(tdir)
+0
-568
git/test/test_refs.py less more
0 # test_refs.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5
6 from itertools import chain
7
8 from git import (
9 Reference,
10 Head,
11 TagReference,
12 RemoteReference,
13 Commit,
14 SymbolicReference,
15 GitCommandError,
16 RefLog
17 )
18 from git.objects.tag import TagObject
19 from git.test.lib import (
20 TestBase,
21 with_rw_repo
22 )
23 from git.util import Actor
24
25 import git.refs as refs
26 import os.path as osp
27
28
29 class TestRefs(TestBase):
30
31 def test_from_path(self):
32 # should be able to create any reference directly
33 for ref_type in (Reference, Head, TagReference, RemoteReference):
34 for name in ('rela_name', 'path/rela_name'):
35 full_path = ref_type.to_full_path(name)
36 instance = ref_type.from_path(self.rorepo, full_path)
37 assert isinstance(instance, ref_type)
38 # END for each name
39 # END for each type
40
41 # invalid path
42 self.assertRaises(ValueError, TagReference, self.rorepo, "refs/invalid/tag")
43 # works without path check
44 TagReference(self.rorepo, "refs/invalid/tag", check_path=False)
45
46 def test_tag_base(self):
47 tag_object_refs = []
48 for tag in self.rorepo.tags:
49 assert "refs/tags" in tag.path
50 assert tag.name
51 assert isinstance(tag.commit, Commit)
52 if tag.tag is not None:
53 tag_object_refs.append(tag)
54 tagobj = tag.tag
55 # have no dict
56 self.assertRaises(AttributeError, setattr, tagobj, 'someattr', 1)
57 assert isinstance(tagobj, TagObject)
58 assert tagobj.tag == tag.name
59 assert isinstance(tagobj.tagger, Actor)
60 assert isinstance(tagobj.tagged_date, int)
61 assert isinstance(tagobj.tagger_tz_offset, int)
62 assert tagobj.message
63 assert tag.object == tagobj
64 # can't assign the object
65 self.assertRaises(AttributeError, setattr, tag, 'object', tagobj)
66 # END if we have a tag object
67 # END for tag in repo-tags
68 assert tag_object_refs
69 assert isinstance(self.rorepo.tags['0.1.5'], TagReference)
70
71 def test_tags_author(self):
72 tag = self.rorepo.tags[0]
73 tagobj = tag.tag
74 assert isinstance(tagobj.tagger, Actor)
75 tagger_name = tagobj.tagger.name
76 assert tagger_name == 'Michael Trier'
77
78 def test_tags(self):
79 # tag refs can point to tag objects or to commits
80 s = set()
81 ref_count = 0
82 for ref in chain(self.rorepo.tags, self.rorepo.heads):
83 ref_count += 1
84 assert isinstance(ref, refs.Reference)
85 assert str(ref) == ref.name
86 assert repr(ref)
87 assert ref == ref
88 assert not ref != ref
89 s.add(ref)
90 # END for each ref
91 assert len(s) == ref_count
92 assert len(s | s) == ref_count
93
94 @with_rw_repo('HEAD', bare=False)
95 def test_heads(self, rwrepo):
96 for head in rwrepo.heads:
97 assert head.name
98 assert head.path
99 assert "refs/heads" in head.path
100 prev_object = head.object
101 cur_object = head.object
102 assert prev_object == cur_object # represent the same git object
103 assert prev_object is not cur_object # but are different instances
104
105 with head.config_writer() as writer:
106 tv = "testopt"
107 writer.set_value(tv, 1)
108 assert writer.get_value(tv) == 1
109 assert head.config_reader().get_value(tv) == 1
110 with head.config_writer() as writer:
111 writer.remove_option(tv)
112
113 # after the clone, we might still have a tracking branch setup
114 head.set_tracking_branch(None)
115 assert head.tracking_branch() is None
116 remote_ref = rwrepo.remotes[0].refs[0]
117 assert head.set_tracking_branch(remote_ref) is head
118 assert head.tracking_branch() == remote_ref
119 head.set_tracking_branch(None)
120 assert head.tracking_branch() is None
121
122 special_name = 'feature#123'
123 special_name_remote_ref = SymbolicReference.create(rwrepo, 'refs/remotes/origin/%s' % special_name)
124 gp_tracking_branch = rwrepo.create_head('gp_tracking#123')
125 special_name_remote_ref = rwrepo.remotes[0].refs[special_name] # get correct type
126 gp_tracking_branch.set_tracking_branch(special_name_remote_ref)
127 assert gp_tracking_branch.tracking_branch().path == special_name_remote_ref.path
128
129 git_tracking_branch = rwrepo.create_head('git_tracking#123')
130 rwrepo.git.branch('-u', special_name_remote_ref.name, git_tracking_branch.name)
131 assert git_tracking_branch.tracking_branch().name == special_name_remote_ref.name
132 # END for each head
133
134 # verify REFLOG gets altered
135 head = rwrepo.head
136 cur_head = head.ref
137 cur_commit = cur_head.commit
138 pcommit = cur_head.commit.parents[0].parents[0]
139 hlog_len = len(head.log())
140 blog_len = len(cur_head.log())
141 assert head.set_reference(pcommit, 'detached head') is head
142 # one new log-entry
143 thlog = head.log()
144 assert len(thlog) == hlog_len + 1
145 assert thlog[-1].oldhexsha == cur_commit.hexsha
146 assert thlog[-1].newhexsha == pcommit.hexsha
147
148 # the ref didn't change though
149 assert len(cur_head.log()) == blog_len
150
151 # head changes once again, cur_head doesn't change
152 head.set_reference(cur_head, 'reattach head')
153 assert len(head.log()) == hlog_len + 2
154 assert len(cur_head.log()) == blog_len
155
156 # adjusting the head-ref also adjust the head, so both reflogs are
157 # altered
158 cur_head.set_commit(pcommit, 'changing commit')
159 assert len(cur_head.log()) == blog_len + 1
160 assert len(head.log()) == hlog_len + 3
161
162 # with automatic dereferencing
163 assert head.set_commit(cur_commit, 'change commit once again') is head
164 assert len(head.log()) == hlog_len + 4
165 assert len(cur_head.log()) == blog_len + 2
166
167 # a new branch has just a single entry
168 other_head = Head.create(rwrepo, 'mynewhead', pcommit, logmsg='new head created')
169 log = other_head.log()
170 assert len(log) == 1
171 assert log[0].oldhexsha == pcommit.NULL_HEX_SHA
172 assert log[0].newhexsha == pcommit.hexsha
173
174 def test_refs(self):
175 types_found = set()
176 for ref in self.rorepo.refs:
177 types_found.add(type(ref))
178 assert len(types_found) >= 3
179
180 def test_is_valid(self):
181 assert not Reference(self.rorepo, 'refs/doesnt/exist').is_valid()
182 assert self.rorepo.head.is_valid()
183 assert self.rorepo.head.reference.is_valid()
184 assert not SymbolicReference(self.rorepo, 'hellothere').is_valid()
185
186 def test_orig_head(self):
187 assert type(self.rorepo.head.orig_head()) == SymbolicReference
188
189 @with_rw_repo('0.1.6')
190 def test_head_checkout_detached_head(self, rw_repo):
191 res = rw_repo.remotes.origin.refs.master.checkout()
192 assert isinstance(res, SymbolicReference)
193 assert res.name == 'HEAD'
194
195 @with_rw_repo('0.1.6')
196 def test_head_reset(self, rw_repo):
197 cur_head = rw_repo.head
198 old_head_commit = cur_head.commit
199 new_head_commit = cur_head.ref.commit.parents[0]
200 cur_head.reset(new_head_commit, index=True) # index only
201 assert cur_head.reference.commit == new_head_commit
202
203 self.assertRaises(ValueError, cur_head.reset, new_head_commit, index=False, working_tree=True)
204 new_head_commit = new_head_commit.parents[0]
205 cur_head.reset(new_head_commit, index=True, working_tree=True) # index + wt
206 assert cur_head.reference.commit == new_head_commit
207
208 # paths - make sure we have something to do
209 rw_repo.index.reset(old_head_commit.parents[0])
210 cur_head.reset(cur_head, paths="test")
211 cur_head.reset(new_head_commit, paths="lib")
212 # hard resets with paths don't work, its all or nothing
213 self.assertRaises(GitCommandError, cur_head.reset, new_head_commit, working_tree=True, paths="lib")
214
215 # we can do a mixed reset, and then checkout from the index though
216 cur_head.reset(new_head_commit)
217 rw_repo.index.checkout(["lib"], force=True)
218
219 # now that we have a write write repo, change the HEAD reference - its
220 # like git-reset --soft
221 heads = rw_repo.heads
222 assert heads
223 for head in heads:
224 cur_head.reference = head
225 assert cur_head.reference == head
226 assert isinstance(cur_head.reference, Head)
227 assert cur_head.commit == head.commit
228 assert not cur_head.is_detached
229 # END for each head
230
231 # detach
232 active_head = heads[0]
233 curhead_commit = active_head.commit
234 cur_head.reference = curhead_commit
235 assert cur_head.commit == curhead_commit
236 assert cur_head.is_detached
237 self.assertRaises(TypeError, getattr, cur_head, "reference")
238
239 # tags are references, hence we can point to them
240 some_tag = rw_repo.tags[0]
241 cur_head.reference = some_tag
242 assert not cur_head.is_detached
243 assert cur_head.commit == some_tag.commit
244 assert isinstance(cur_head.reference, TagReference)
245
246 # put HEAD back to a real head, otherwise everything else fails
247 cur_head.reference = active_head
248
249 # type check
250 self.assertRaises(ValueError, setattr, cur_head, "reference", "that")
251
252 # head handling
253 commit = 'HEAD'
254 prev_head_commit = cur_head.commit
255 for count, new_name in enumerate(("my_new_head", "feature/feature1")):
256 actual_commit = commit + "^" * count
257 new_head = Head.create(rw_repo, new_name, actual_commit)
258 assert new_head.is_detached
259 assert cur_head.commit == prev_head_commit
260 assert isinstance(new_head, Head)
261 # already exists, but has the same value, so its fine
262 Head.create(rw_repo, new_name, new_head.commit)
263
264 # its not fine with a different value
265 self.assertRaises(OSError, Head.create, rw_repo, new_name, new_head.commit.parents[0])
266
267 # force it
268 new_head = Head.create(rw_repo, new_name, actual_commit, force=True)
269 old_path = new_head.path
270 old_name = new_head.name
271
272 assert new_head.rename("hello").name == "hello"
273 assert new_head.rename("hello/world").name == "hello/world"
274 assert new_head.rename(old_name).name == old_name and new_head.path == old_path
275
276 # rename with force
277 tmp_head = Head.create(rw_repo, "tmphead")
278 self.assertRaises(GitCommandError, tmp_head.rename, new_head)
279 tmp_head.rename(new_head, force=True)
280 assert tmp_head == new_head and tmp_head.object == new_head.object
281
282 logfile = RefLog.path(tmp_head)
283 assert osp.isfile(logfile)
284 Head.delete(rw_repo, tmp_head)
285 # deletion removes the log as well
286 assert not osp.isfile(logfile)
287 heads = rw_repo.heads
288 assert tmp_head not in heads and new_head not in heads
289 # force on deletion testing would be missing here, code looks okay though ;)
290 # END for each new head name
291 self.assertRaises(TypeError, RemoteReference.create, rw_repo, "some_name")
292
293 # tag ref
294 tag_name = "5.0.2"
295 TagReference.create(rw_repo, tag_name)
296 self.assertRaises(GitCommandError, TagReference.create, rw_repo, tag_name)
297 light_tag = TagReference.create(rw_repo, tag_name, "HEAD~1", force=True)
298 assert isinstance(light_tag, TagReference)
299 assert light_tag.name == tag_name
300 assert light_tag.commit == cur_head.commit.parents[0]
301 assert light_tag.tag is None
302
303 # tag with tag object
304 other_tag_name = "releases/1.0.2RC"
305 msg = "my mighty tag\nsecond line"
306 obj_tag = TagReference.create(rw_repo, other_tag_name, message=msg)
307 assert isinstance(obj_tag, TagReference)
308 assert obj_tag.name == other_tag_name
309 assert obj_tag.commit == cur_head.commit
310 assert obj_tag.tag is not None
311
312 TagReference.delete(rw_repo, light_tag, obj_tag)
313 tags = rw_repo.tags
314 assert light_tag not in tags and obj_tag not in tags
315
316 # remote deletion
317 remote_refs_so_far = 0
318 remotes = rw_repo.remotes
319 assert remotes
320 for remote in remotes:
321 refs = remote.refs
322
323 # If a HEAD exists, it must be deleted first. Otherwise it might
324 # end up pointing to an invalid ref it the ref was deleted before.
325 remote_head_name = "HEAD"
326 if remote_head_name in refs:
327 RemoteReference.delete(rw_repo, refs[remote_head_name])
328 del(refs[remote_head_name])
329 # END handle HEAD deletion
330
331 RemoteReference.delete(rw_repo, *refs)
332 remote_refs_so_far += len(refs)
333 for ref in refs:
334 assert ref.remote_name == remote.name
335 # END for each ref to delete
336 assert remote_refs_so_far
337
338 for remote in remotes:
339 # remotes without references should produce an empty list
340 self.assertEqual(remote.refs, [])
341 # END for each remote
342
343 # change where the active head points to
344 if cur_head.is_detached:
345 cur_head.reference = rw_repo.heads[0]
346
347 head = cur_head.reference
348 old_commit = head.commit
349 head.commit = old_commit.parents[0]
350 assert head.commit == old_commit.parents[0]
351 assert head.commit == cur_head.commit
352 head.commit = old_commit
353
354 # setting a non-commit as commit fails, but succeeds as object
355 head_tree = head.commit.tree
356 self.assertRaises(ValueError, setattr, head, 'commit', head_tree)
357 assert head.commit == old_commit # and the ref did not change
358 # we allow heds to point to any object
359 head.object = head_tree
360 assert head.object == head_tree
361 # cannot query tree as commit
362 self.assertRaises(TypeError, getattr, head, 'commit')
363
364 # set the commit directly using the head. This would never detach the head
365 assert not cur_head.is_detached
366 head.object = old_commit
367 cur_head.reference = head.commit
368 assert cur_head.is_detached
369 parent_commit = head.commit.parents[0]
370 assert cur_head.is_detached
371 cur_head.commit = parent_commit
372 assert cur_head.is_detached and cur_head.commit == parent_commit
373
374 cur_head.reference = head
375 assert not cur_head.is_detached
376 cur_head.commit = parent_commit
377 assert not cur_head.is_detached
378 assert head.commit == parent_commit
379
380 # test checkout
381 active_branch = rw_repo.active_branch
382 for head in rw_repo.heads:
383 checked_out_head = head.checkout()
384 assert checked_out_head == head
385 # END for each head to checkout
386
387 # checkout with branch creation
388 new_head = active_branch.checkout(b="new_head")
389 assert active_branch != rw_repo.active_branch
390 assert new_head == rw_repo.active_branch
391
392 # checkout with force as we have a changed a file
393 # clear file
394 open(new_head.commit.tree.blobs[-1].abspath, 'w').close()
395 assert len(new_head.commit.diff(None))
396
397 # create a new branch that is likely to touch the file we changed
398 far_away_head = rw_repo.create_head("far_head", 'HEAD~100')
399 self.assertRaises(GitCommandError, far_away_head.checkout)
400 assert active_branch == active_branch.checkout(force=True)
401 assert rw_repo.head.reference != far_away_head
402
403 # test reference creation
404 partial_ref = 'sub/ref'
405 full_ref = 'refs/%s' % partial_ref
406 ref = Reference.create(rw_repo, partial_ref)
407 assert ref.path == full_ref
408 assert ref.object == rw_repo.head.commit
409
410 self.assertRaises(OSError, Reference.create, rw_repo, full_ref, 'HEAD~20')
411 # it works if it is at the same spot though and points to the same reference
412 assert Reference.create(rw_repo, full_ref, 'HEAD').path == full_ref
413 Reference.delete(rw_repo, full_ref)
414
415 # recreate the reference using a full_ref
416 ref = Reference.create(rw_repo, full_ref)
417 assert ref.path == full_ref
418 assert ref.object == rw_repo.head.commit
419
420 # recreate using force
421 ref = Reference.create(rw_repo, partial_ref, 'HEAD~1', force=True)
422 assert ref.path == full_ref
423 assert ref.object == rw_repo.head.commit.parents[0]
424
425 # rename it
426 orig_obj = ref.object
427 for name in ('refs/absname', 'rela_name', 'feature/rela_name'):
428 ref_new_name = ref.rename(name)
429 assert isinstance(ref_new_name, Reference)
430 assert name in ref_new_name.path
431 assert ref_new_name.object == orig_obj
432 assert ref_new_name == ref
433 # END for each name type
434
435 # References that don't exist trigger an error if we want to access them
436 self.assertRaises(ValueError, getattr, Reference(rw_repo, "refs/doesntexist"), 'commit')
437
438 # exists, fail unless we force
439 ex_ref_path = far_away_head.path
440 self.assertRaises(OSError, ref.rename, ex_ref_path)
441 # if it points to the same commit it works
442 far_away_head.commit = ref.commit
443 ref.rename(ex_ref_path)
444 assert ref.path == ex_ref_path and ref.object == orig_obj
445 assert ref.rename(ref.path).path == ex_ref_path # rename to same name
446
447 # create symbolic refs
448 symref_path = "symrefs/sym"
449 symref = SymbolicReference.create(rw_repo, symref_path, cur_head.reference)
450 assert symref.path == symref_path
451 assert symref.reference == cur_head.reference
452
453 self.assertRaises(OSError, SymbolicReference.create, rw_repo, symref_path, cur_head.reference.commit)
454 # it works if the new ref points to the same reference
455 SymbolicReference.create(rw_repo, symref.path, symref.reference).path == symref.path # @NoEffect
456 SymbolicReference.delete(rw_repo, symref)
457 # would raise if the symref wouldn't have been deletedpbl
458 symref = SymbolicReference.create(rw_repo, symref_path, cur_head.reference)
459
460 # test symbolic references which are not at default locations like HEAD
461 # or FETCH_HEAD - they may also be at spots in refs of course
462 symbol_ref_path = "refs/symbol_ref"
463 symref = SymbolicReference(rw_repo, symbol_ref_path)
464 assert symref.path == symbol_ref_path
465 symbol_ref_abspath = osp.join(rw_repo.git_dir, symref.path)
466
467 # set it
468 symref.reference = new_head
469 assert symref.reference == new_head
470 assert osp.isfile(symbol_ref_abspath)
471 assert symref.commit == new_head.commit
472
473 for name in ('absname', 'folder/rela_name'):
474 symref_new_name = symref.rename(name)
475 assert isinstance(symref_new_name, SymbolicReference)
476 assert name in symref_new_name.path
477 assert symref_new_name.reference == new_head
478 assert symref_new_name == symref
479 assert not symref.is_detached
480 # END for each ref
481
482 # create a new non-head ref just to be sure we handle it even if packed
483 Reference.create(rw_repo, full_ref)
484
485 # test ref listing - assure we have packed refs
486 rw_repo.git.pack_refs(all=True, prune=True)
487 heads = rw_repo.heads
488 assert heads
489 assert new_head in heads
490 assert active_branch in heads
491 assert rw_repo.tags
492
493 # we should be able to iterate all symbolic refs as well - in that case
494 # we should expect only symbolic references to be returned
495 for symref in SymbolicReference.iter_items(rw_repo):
496 assert not symref.is_detached
497
498 # when iterating references, we can get references and symrefs
499 # when deleting all refs, I'd expect them to be gone ! Even from
500 # the packed ones
501 # For this to work, we must not be on any branch
502 rw_repo.head.reference = rw_repo.head.commit
503 deleted_refs = set()
504 for ref in Reference.iter_items(rw_repo):
505 if ref.is_detached:
506 ref.delete(rw_repo, ref)
507 deleted_refs.add(ref)
508 # END delete ref
509 # END for each ref to iterate and to delete
510 assert deleted_refs
511
512 for ref in Reference.iter_items(rw_repo):
513 if ref.is_detached:
514 assert ref not in deleted_refs
515 # END for each ref
516
517 # reattach head - head will not be returned if it is not a symbolic
518 # ref
519 rw_repo.head.reference = Head.create(rw_repo, "master")
520
521 # At least the head should still exist
522 assert osp.isfile(osp.join(rw_repo.git_dir, 'HEAD'))
523 refs = list(SymbolicReference.iter_items(rw_repo))
524 assert len(refs) == 1
525
526 # test creation of new refs from scratch
527 for path in ("basename", "dir/somename", "dir2/subdir/basename"):
528 # REFERENCES
529 ############
530 fpath = Reference.to_full_path(path)
531 ref_fp = Reference.from_path(rw_repo, fpath)
532 assert not ref_fp.is_valid()
533 ref = Reference(rw_repo, fpath)
534 assert ref == ref_fp
535
536 # can be created by assigning a commit
537 ref.commit = rw_repo.head.commit
538 assert ref.is_valid()
539
540 # if the assignment raises, the ref doesn't exist
541 Reference.delete(ref.repo, ref.path)
542 assert not ref.is_valid()
543 self.assertRaises(ValueError, setattr, ref, 'commit', "nonsense")
544 assert not ref.is_valid()
545
546 # I am sure I had my reason to make it a class method at first, but
547 # now it doesn't make so much sense anymore, want an instance method as well
548 # See http://byronimo.lighthouseapp.com/projects/51787-gitpython/tickets/27
549 Reference.delete(ref.repo, ref.path)
550 assert not ref.is_valid()
551
552 ref.object = rw_repo.head.commit
553 assert ref.is_valid()
554
555 Reference.delete(ref.repo, ref.path)
556 assert not ref.is_valid()
557 self.assertRaises(ValueError, setattr, ref, 'object', "nonsense")
558 assert not ref.is_valid()
559
560 # END for each path
561
562 def test_dereference_recursive(self):
563 # for now, just test the HEAD
564 assert SymbolicReference.dereference_recursive(self.rorepo, 'HEAD')
565
566 def test_reflog(self):
567 assert isinstance(self.rorepo.heads.master.log(), RefLog)
+0
-653
git/test/test_remote.py less more
0 # test_remote.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5
6 import random
7 import tempfile
8 from unittest import skipIf
9
10 from git import (
11 RemoteProgress,
12 FetchInfo,
13 Reference,
14 SymbolicReference,
15 Head,
16 Commit,
17 PushInfo,
18 RemoteReference,
19 TagReference,
20 Remote,
21 GitCommandError
22 )
23 from git.cmd import Git
24 from git.test.lib import (
25 TestBase,
26 with_rw_repo,
27 with_rw_and_rw_remote_repo,
28 fixture,
29 GIT_DAEMON_PORT
30 )
31 from git.util import rmtree, HIDE_WINDOWS_FREEZE_ERRORS
32 import os.path as osp
33
34
35 # assure we have repeatable results
36 random.seed(0)
37
38
39 class TestRemoteProgress(RemoteProgress):
40 __slots__ = ("_seen_lines", "_stages_per_op", '_num_progress_messages')
41
42 def __init__(self):
43 super(TestRemoteProgress, self).__init__()
44 self._seen_lines = []
45 self._stages_per_op = {}
46 self._num_progress_messages = 0
47
48 def _parse_progress_line(self, line):
49 # we may remove the line later if it is dropped
50 # Keep it for debugging
51 self._seen_lines.append(line)
52 rval = super(TestRemoteProgress, self)._parse_progress_line(line)
53 return rval
54
55 def line_dropped(self, line):
56 try:
57 self._seen_lines.remove(line)
58 except ValueError:
59 pass
60
61 def update(self, op_code, cur_count, max_count=None, message=''):
62 # check each stage only comes once
63 op_id = op_code & self.OP_MASK
64 assert op_id in (self.COUNTING, self.COMPRESSING, self.WRITING)
65
66 if op_code & self.WRITING > 0:
67 if op_code & self.BEGIN > 0:
68 assert not message, 'should not have message when remote begins writing'
69 elif op_code & self.END > 0:
70 assert message
71 assert not message.startswith(', '), "Sanitize progress messages: '%s'" % message
72 assert not message.endswith(', '), "Sanitize progress messages: '%s'" % message
73
74 self._stages_per_op.setdefault(op_id, 0)
75 self._stages_per_op[op_id] = self._stages_per_op[op_id] | (op_code & self.STAGE_MASK)
76
77 if op_code & (self.WRITING | self.END) == (self.WRITING | self.END):
78 assert message
79 # END check we get message
80
81 self._num_progress_messages += 1
82
83 def make_assertion(self):
84 # we don't always receive messages
85 if not self._seen_lines:
86 return
87
88 # sometimes objects are not compressed which is okay
89 assert len(self._seen_ops) in (2, 3), len(self._seen_ops)
90 assert self._stages_per_op
91
92 # must have seen all stages
93 for _op, stages in self._stages_per_op.items():
94 assert stages & self.STAGE_MASK == self.STAGE_MASK
95 # END for each op/stage
96
97 def assert_received_message(self):
98 assert self._num_progress_messages
99
100
101 class TestRemote(TestBase):
102
103 def tearDown(self):
104 import gc
105 gc.collect()
106
107 def _print_fetchhead(self, repo):
108 with open(osp.join(repo.git_dir, "FETCH_HEAD")):
109 pass
110
111 def _do_test_fetch_result(self, results, remote):
112 # self._print_fetchhead(remote.repo)
113 self.assertGreater(len(results), 0)
114 self.assertIsInstance(results[0], FetchInfo)
115 for info in results:
116 self.assertIsInstance(info.note, str)
117 if isinstance(info.ref, Reference):
118 self.assertTrue(info.flags)
119 # END reference type flags handling
120 self.assertIsInstance(info.ref, (SymbolicReference, Reference))
121 if info.flags & (info.FORCED_UPDATE | info.FAST_FORWARD):
122 self.assertIsInstance(info.old_commit, Commit)
123 else:
124 self.assertIsNone(info.old_commit)
125 # END forced update checking
126 # END for each info
127
128 def _do_test_push_result(self, results, remote):
129 self.assertGreater(len(results), 0)
130 self.assertIsInstance(results[0], PushInfo)
131 for info in results:
132 self.assertTrue(info.flags)
133 self.assertIsInstance(info.summary, str)
134 if info.old_commit is not None:
135 self.assertIsInstance(info.old_commit, Commit)
136 if info.flags & info.ERROR:
137 has_one = False
138 for bitflag in (info.REJECTED, info.REMOTE_REJECTED, info.REMOTE_FAILURE):
139 has_one |= bool(info.flags & bitflag)
140 # END for each bitflag
141 self.assertTrue(has_one)
142 else:
143 # there must be a remote commit
144 if info.flags & info.DELETED == 0:
145 self.assertIsInstance(info.local_ref, Reference)
146 else:
147 self.assertIsNone(info.local_ref)
148 self.assertIn(type(info.remote_ref), (TagReference, RemoteReference))
149 # END error checking
150 # END for each info
151
152 def _do_test_fetch_info(self, repo):
153 self.assertRaises(ValueError, FetchInfo._from_line, repo, "nonsense", '')
154 self.assertRaises(
155 ValueError, FetchInfo._from_line, repo, "? [up to date] 0.1.7RC -> origin/0.1.7RC", '')
156
157 def _commit_random_file(self, repo):
158 # Create a file with a random name and random data and commit it to repo.
159 # Return the committed absolute file path
160 index = repo.index
161 new_file = self._make_file(osp.basename(tempfile.mktemp()), str(random.random()), repo)
162 index.add([new_file])
163 index.commit("Committing %s" % new_file)
164 return new_file
165
166 def _do_test_fetch(self, remote, rw_repo, remote_repo):
167 # specialized fetch testing to de-clutter the main test
168 self._do_test_fetch_info(rw_repo)
169
170 def fetch_and_test(remote, **kwargs):
171 progress = TestRemoteProgress()
172 kwargs['progress'] = progress
173 res = remote.fetch(**kwargs)
174 progress.make_assertion()
175 self._do_test_fetch_result(res, remote)
176 return res
177 # END fetch and check
178
179 def get_info(res, remote, name):
180 return res["%s/%s" % (remote, name)]
181
182 # put remote head to master as it is guaranteed to exist
183 remote_repo.head.reference = remote_repo.heads.master
184
185 res = fetch_and_test(remote)
186 # all up to date
187 for info in res:
188 self.assertTrue(info.flags & info.HEAD_UPTODATE)
189
190 # rewind remote head to trigger rejection
191 # index must be false as remote is a bare repo
192 rhead = remote_repo.head
193 remote_commit = rhead.commit
194 rhead.reset("HEAD~2", index=False)
195 res = fetch_and_test(remote)
196 mkey = "%s/%s" % (remote, 'master')
197 master_info = res[mkey]
198 self.assertTrue(master_info.flags & FetchInfo.FORCED_UPDATE)
199 self.assertIsNotNone(master_info.note)
200
201 # normal fast forward - set head back to previous one
202 rhead.commit = remote_commit
203 res = fetch_and_test(remote)
204 self.assertTrue(res[mkey].flags & FetchInfo.FAST_FORWARD)
205
206 # new remote branch
207 new_remote_branch = Head.create(remote_repo, "new_branch")
208 res = fetch_and_test(remote)
209 new_branch_info = get_info(res, remote, new_remote_branch)
210 self.assertTrue(new_branch_info.flags & FetchInfo.NEW_HEAD)
211
212 # remote branch rename ( causes creation of a new one locally )
213 new_remote_branch.rename("other_branch_name")
214 res = fetch_and_test(remote)
215 other_branch_info = get_info(res, remote, new_remote_branch)
216 self.assertEqual(other_branch_info.ref.commit, new_branch_info.ref.commit)
217
218 # remove new branch
219 Head.delete(new_remote_branch.repo, new_remote_branch)
220 res = fetch_and_test(remote)
221 # deleted remote will not be fetched
222 self.assertRaises(IndexError, get_info, res, remote, new_remote_branch)
223
224 # prune stale tracking branches
225 stale_refs = remote.stale_refs
226 self.assertEqual(len(stale_refs), 2)
227 self.assertIsInstance(stale_refs[0], RemoteReference)
228 RemoteReference.delete(rw_repo, *stale_refs)
229
230 # test single branch fetch with refspec including target remote
231 res = fetch_and_test(remote, refspec="master:refs/remotes/%s/master" % remote)
232 self.assertEqual(len(res), 1)
233 self.assertTrue(get_info(res, remote, 'master'))
234
235 # ... with respec and no target
236 res = fetch_and_test(remote, refspec='master')
237 self.assertEqual(len(res), 1)
238
239 # ... multiple refspecs ... works, but git command returns with error if one ref is wrong without
240 # doing anything. This is new in later binaries
241 # res = fetch_and_test(remote, refspec=['master', 'fred'])
242 # self.assertEqual(len(res), 1)
243
244 # add new tag reference
245 rtag = TagReference.create(remote_repo, "1.0-RV_hello.there")
246 res = fetch_and_test(remote, tags=True)
247 tinfo = res[str(rtag)]
248 self.assertIsInstance(tinfo.ref, TagReference)
249 self.assertEqual(tinfo.ref.commit, rtag.commit)
250 self.assertTrue(tinfo.flags & tinfo.NEW_TAG)
251
252 # adjust the local tag commit
253 Reference.set_object(rtag, rhead.commit.parents[0].parents[0])
254
255 # as of git 2.20 one cannot clobber local tags that have changed without
256 # specifying --force, and the test assumes you can clobber, so...
257 force = None
258 if rw_repo.git.version_info[:2] >= (2, 20):
259 force = True
260 res = fetch_and_test(remote, tags=True, force=force)
261 tinfo = res[str(rtag)]
262 self.assertEqual(tinfo.commit, rtag.commit)
263 self.assertTrue(tinfo.flags & tinfo.TAG_UPDATE)
264
265 # delete remote tag - local one will stay
266 TagReference.delete(remote_repo, rtag)
267 res = fetch_and_test(remote, tags=True)
268 self.assertRaises(IndexError, get_info, res, remote, str(rtag))
269
270 # provoke to receive actual objects to see what kind of output we have to
271 # expect. For that we need a remote transport protocol
272 # Create a new UN-shared repo and fetch into it after we pushed a change
273 # to the shared repo
274 other_repo_dir = tempfile.mktemp("other_repo")
275 # must clone with a local path for the repo implementation not to freak out
276 # as it wants local paths only ( which I can understand )
277 other_repo = remote_repo.clone(other_repo_dir, shared=False)
278 remote_repo_url = osp.basename(remote_repo.git_dir) # git-daemon runs with appropriate `--base-path`.
279 remote_repo_url = Git.polish_url("git://localhost:%s/%s" % (GIT_DAEMON_PORT, remote_repo_url))
280
281 # put origin to git-url
282 other_origin = other_repo.remotes.origin
283 with other_origin.config_writer as cw:
284 cw.set("url", remote_repo_url)
285 # it automatically creates alternates as remote_repo is shared as well.
286 # It will use the transport though and ignore alternates when fetching
287 # assert not other_repo.alternates # this would fail
288
289 # assure we are in the right state
290 rw_repo.head.reset(remote.refs.master, working_tree=True)
291 try:
292 self._commit_random_file(rw_repo)
293 remote.push(rw_repo.head.reference)
294
295 # here I would expect to see remote-information about packing
296 # objects and so on. Unfortunately, this does not happen
297 # if we are redirecting the output - git explicitly checks for this
298 # and only provides progress information to ttys
299 res = fetch_and_test(other_origin)
300 finally:
301 rmtree(other_repo_dir)
302 # END test and cleanup
303
304 def _assert_push_and_pull(self, remote, rw_repo, remote_repo):
305 # push our changes
306 lhead = rw_repo.head
307 # assure we are on master and it is checked out where the remote is
308 try:
309 lhead.reference = rw_repo.heads.master
310 except AttributeError:
311 # if the author is on a non-master branch, the clones might not have
312 # a local master yet. We simply create it
313 lhead.reference = rw_repo.create_head('master')
314 # END master handling
315 lhead.reset(remote.refs.master, working_tree=True)
316
317 # push without spec should fail ( without further configuration )
318 # well, works nicely
319 # self.assertRaises(GitCommandError, remote.push)
320
321 # simple file push
322 self._commit_random_file(rw_repo)
323 progress = TestRemoteProgress()
324 res = remote.push(lhead.reference, progress)
325 self.assertIsInstance(res, list)
326 self._do_test_push_result(res, remote)
327 progress.make_assertion()
328
329 # rejected - undo last commit
330 lhead.reset("HEAD~1")
331 res = remote.push(lhead.reference)
332 self.assertTrue(res[0].flags & PushInfo.ERROR)
333 self.assertTrue(res[0].flags & PushInfo.REJECTED)
334 self._do_test_push_result(res, remote)
335
336 # force rejected pull
337 res = remote.push('+%s' % lhead.reference)
338 self.assertEqual(res[0].flags & PushInfo.ERROR, 0)
339 self.assertTrue(res[0].flags & PushInfo.FORCED_UPDATE)
340 self._do_test_push_result(res, remote)
341
342 # invalid refspec
343 self.assertRaises(GitCommandError, remote.push, "hellothere")
344
345 # push new tags
346 progress = TestRemoteProgress()
347 to_be_updated = "my_tag.1.0RV"
348 new_tag = TagReference.create(rw_repo, to_be_updated) # @UnusedVariable
349 other_tag = TagReference.create(rw_repo, "my_obj_tag.2.1aRV", message="my message")
350 res = remote.push(progress=progress, tags=True)
351 self.assertTrue(res[-1].flags & PushInfo.NEW_TAG)
352 progress.make_assertion()
353 self._do_test_push_result(res, remote)
354
355 # update push new tags
356 # Rejection is default
357 new_tag = TagReference.create(rw_repo, to_be_updated, ref='HEAD~1', force=True)
358 res = remote.push(tags=True)
359 self._do_test_push_result(res, remote)
360 self.assertTrue(res[-1].flags & PushInfo.REJECTED)
361 self.assertTrue(res[-1].flags & PushInfo.ERROR)
362
363 # push force this tag
364 res = remote.push("+%s" % new_tag.path)
365 self.assertEqual(res[-1].flags & PushInfo.ERROR, 0)
366 self.assertTrue(res[-1].flags & PushInfo.FORCED_UPDATE)
367
368 # delete tag - have to do it using refspec
369 res = remote.push(":%s" % new_tag.path)
370 self._do_test_push_result(res, remote)
371 self.assertTrue(res[0].flags & PushInfo.DELETED)
372 # Currently progress is not properly transferred, especially not using
373 # the git daemon
374 # progress.assert_received_message()
375
376 # push new branch
377 new_head = Head.create(rw_repo, "my_new_branch")
378 progress = TestRemoteProgress()
379 res = remote.push(new_head, progress)
380 self.assertGreater(len(res), 0)
381 self.assertTrue(res[0].flags & PushInfo.NEW_HEAD)
382 progress.make_assertion()
383 self._do_test_push_result(res, remote)
384
385 # rejected stale delete
386 force_with_lease = "%s:0000000000000000000000000000000000000000" % new_head.path
387 res = remote.push(":%s" % new_head.path, force_with_lease=force_with_lease)
388 self.assertTrue(res[0].flags & PushInfo.ERROR)
389 self.assertTrue(res[0].flags & PushInfo.REJECTED)
390 self.assertIsNone(res[0].local_ref)
391 self._do_test_push_result(res, remote)
392
393 # delete new branch on the remote end and locally
394 res = remote.push(":%s" % new_head.path)
395 self._do_test_push_result(res, remote)
396 Head.delete(rw_repo, new_head)
397 self.assertTrue(res[-1].flags & PushInfo.DELETED)
398
399 # --all
400 res = remote.push(all=True)
401 self._do_test_push_result(res, remote)
402
403 remote.pull('master')
404
405 # cleanup - delete created tags and branches as we are in an innerloop on
406 # the same repository
407 TagReference.delete(rw_repo, new_tag, other_tag)
408 remote.push(":%s" % other_tag.path)
409
410 @skipIf(HIDE_WINDOWS_FREEZE_ERRORS, "FIXME: Freezes!")
411 @with_rw_and_rw_remote_repo('0.1.6')
412 def test_base(self, rw_repo, remote_repo):
413 num_remotes = 0
414 remote_set = set()
415 ran_fetch_test = False
416
417 for remote in rw_repo.remotes:
418 num_remotes += 1
419 self.assertEqual(remote, remote)
420 self.assertNotEqual(str(remote), repr(remote))
421 remote_set.add(remote)
422 remote_set.add(remote) # should already exist
423 # REFS
424 refs = remote.refs
425 self.assertTrue(refs)
426 for ref in refs:
427 self.assertEqual(ref.remote_name, remote.name)
428 self.assertTrue(ref.remote_head)
429 # END for each ref
430
431 # OPTIONS
432 # cannot use 'fetch' key anymore as it is now a method
433 for opt in ("url",):
434 val = getattr(remote, opt)
435 reader = remote.config_reader
436 assert reader.get(opt) == val
437 assert reader.get_value(opt, None) == val
438
439 # unable to write with a reader
440 self.assertRaises(IOError, reader.set, opt, "test")
441
442 # change value
443 with remote.config_writer as writer:
444 new_val = "myval"
445 writer.set(opt, new_val)
446 assert writer.get(opt) == new_val
447 writer.set(opt, val)
448 assert writer.get(opt) == val
449 assert getattr(remote, opt) == val
450 # END for each default option key
451
452 # RENAME
453 other_name = "totally_other_name"
454 prev_name = remote.name
455 self.assertEqual(remote.rename(other_name), remote)
456 self.assertNotEqual(prev_name, remote.name)
457 # multiple times
458 for _ in range(2):
459 self.assertEqual(remote.rename(prev_name).name, prev_name)
460 # END for each rename ( back to prev_name )
461
462 # PUSH/PULL TESTING
463 self._assert_push_and_pull(remote, rw_repo, remote_repo)
464
465 # FETCH TESTING
466 # Only for remotes - local cases are the same or less complicated
467 # as additional progress information will never be emitted
468 if remote.name == "daemon_origin":
469 self._do_test_fetch(remote, rw_repo, remote_repo)
470 ran_fetch_test = True
471 # END fetch test
472
473 remote.update()
474 # END for each remote
475
476 self.assertTrue(ran_fetch_test)
477 self.assertTrue(num_remotes)
478 self.assertEqual(num_remotes, len(remote_set))
479
480 origin = rw_repo.remote('origin')
481 assert origin == rw_repo.remotes.origin
482
483 # Verify we can handle prunes when fetching
484 # stderr lines look like this: x [deleted] (none) -> origin/experiment-2012
485 # These should just be skipped
486 # If we don't have a manual checkout, we can't actually assume there are any non-master branches
487 remote_repo.create_head("myone_for_deletion")
488 # Get the branch - to be pruned later
489 origin.fetch()
490
491 num_deleted = False
492 for branch in remote_repo.heads:
493 if branch.name != 'master':
494 branch.delete(remote_repo, branch, force=True)
495 num_deleted += 1
496 # end
497 # end for each branch
498 self.assertGreater(num_deleted, 0)
499 self.assertEqual(len(rw_repo.remotes.origin.fetch(prune=True)), 1, "deleted everything but master")
500
501 @with_rw_repo('HEAD', bare=True)
502 def test_creation_and_removal(self, bare_rw_repo):
503 new_name = "test_new_one"
504 arg_list = (new_name, "git@server:hello.git")
505 remote = Remote.create(bare_rw_repo, *arg_list)
506 self.assertEqual(remote.name, "test_new_one")
507 self.assertIn(remote, bare_rw_repo.remotes)
508 self.assertTrue(remote.exists())
509
510 # create same one again
511 self.assertRaises(GitCommandError, Remote.create, bare_rw_repo, *arg_list)
512
513 Remote.remove(bare_rw_repo, new_name)
514 self.assertTrue(remote.exists()) # We still have a cache that doesn't know we were deleted by name
515 remote._clear_cache()
516 assert not remote.exists() # Cache should be renewed now. This is an issue ...
517
518 for remote in bare_rw_repo.remotes:
519 if remote.name == new_name:
520 raise AssertionError("Remote removal failed")
521 # END if deleted remote matches existing remote's name
522 # END for each remote
523
524 # Issue #262 - the next call would fail if bug wasn't fixed
525 bare_rw_repo.create_remote('bogus', '/bogus/path', mirror='push')
526
527 def test_fetch_info(self):
528 # assure we can handle remote-tracking branches
529 fetch_info_line_fmt = "c437ee5deb8d00cf02f03720693e4c802e99f390 not-for-merge %s '0.3' of "
530 fetch_info_line_fmt += "git://github.com/gitpython-developers/GitPython"
531 remote_info_line_fmt = "* [new branch] nomatter -> %s"
532
533 self.assertRaises(ValueError, FetchInfo._from_line, self.rorepo,
534 remote_info_line_fmt % "refs/something/branch",
535 "269c498e56feb93e408ed4558c8138d750de8893\t\t/Users/ben/test/foo\n")
536
537 fi = FetchInfo._from_line(self.rorepo,
538 remote_info_line_fmt % "local/master",
539 fetch_info_line_fmt % 'remote-tracking branch')
540 assert not fi.ref.is_valid()
541 self.assertEqual(fi.ref.name, "local/master")
542
543 # handles non-default refspecs: One can specify a different path in refs/remotes
544 # or a special path just in refs/something for instance
545
546 fi = FetchInfo._from_line(self.rorepo,
547 remote_info_line_fmt % "subdir/tagname",
548 fetch_info_line_fmt % 'tag')
549
550 self.assertIsInstance(fi.ref, TagReference)
551 assert fi.ref.path.startswith('refs/tags'), fi.ref.path
552
553 # it could be in a remote direcftory though
554 fi = FetchInfo._from_line(self.rorepo,
555 remote_info_line_fmt % "remotename/tags/tagname",
556 fetch_info_line_fmt % 'tag')
557
558 self.assertIsInstance(fi.ref, TagReference)
559 assert fi.ref.path.startswith('refs/remotes/'), fi.ref.path
560
561 # it can also be anywhere !
562 tag_path = "refs/something/remotename/tags/tagname"
563 fi = FetchInfo._from_line(self.rorepo,
564 remote_info_line_fmt % tag_path,
565 fetch_info_line_fmt % 'tag')
566
567 self.assertIsInstance(fi.ref, TagReference)
568 self.assertEqual(fi.ref.path, tag_path)
569
570 # branches default to refs/remotes
571 fi = FetchInfo._from_line(self.rorepo,
572 remote_info_line_fmt % "remotename/branch",
573 fetch_info_line_fmt % 'branch')
574
575 self.assertIsInstance(fi.ref, RemoteReference)
576 self.assertEqual(fi.ref.remote_name, 'remotename')
577
578 # but you can force it anywhere, in which case we only have a references
579 fi = FetchInfo._from_line(self.rorepo,
580 remote_info_line_fmt % "refs/something/branch",
581 fetch_info_line_fmt % 'branch')
582
583 assert type(fi.ref) is Reference, type(fi.ref)
584 self.assertEqual(fi.ref.path, "refs/something/branch")
585
586 def test_uncommon_branch_names(self):
587 stderr_lines = fixture('uncommon_branch_prefix_stderr').decode('ascii').splitlines()
588 fetch_lines = fixture('uncommon_branch_prefix_FETCH_HEAD').decode('ascii').splitlines()
589
590 # The contents of the files above must be fetched with a custom refspec:
591 # +refs/pull/*:refs/heads/pull/*
592 res = [FetchInfo._from_line('ShouldntMatterRepo', stderr, fetch_line)
593 for stderr, fetch_line in zip(stderr_lines, fetch_lines)]
594 self.assertGreater(len(res), 0)
595 self.assertEqual(res[0].remote_ref_path, 'refs/pull/1/head')
596 self.assertEqual(res[0].ref.path, 'refs/heads/pull/1/head')
597 self.assertIsInstance(res[0].ref, Head)
598
599 @with_rw_repo('HEAD', bare=False)
600 def test_multiple_urls(self, rw_repo):
601 # test addresses
602 test1 = 'https://github.com/gitpython-developers/GitPython'
603 test2 = 'https://github.com/gitpython-developers/gitdb'
604 test3 = 'https://github.com/gitpython-developers/smmap'
605
606 remote = rw_repo.remotes[0]
607 # Testing setting a single URL
608 remote.set_url(test1)
609 self.assertEqual(list(remote.urls), [test1])
610
611 # Testing replacing that single URL
612 remote.set_url(test1)
613 self.assertEqual(list(remote.urls), [test1])
614 # Testing adding new URLs
615 remote.set_url(test2, add=True)
616 self.assertEqual(list(remote.urls), [test1, test2])
617 remote.set_url(test3, add=True)
618 self.assertEqual(list(remote.urls), [test1, test2, test3])
619 # Testing removing an URL
620 remote.set_url(test2, delete=True)
621 self.assertEqual(list(remote.urls), [test1, test3])
622 # Testing changing an URL
623 remote.set_url(test2, test3)
624 self.assertEqual(list(remote.urls), [test1, test2])
625
626 # will raise: fatal: --add --delete doesn't make sense
627 self.assertRaises(GitCommandError, remote.set_url, test2, add=True, delete=True)
628
629 # Testing on another remote, with the add/delete URL
630 remote = rw_repo.create_remote('another', url=test1)
631 remote.add_url(test2)
632 self.assertEqual(list(remote.urls), [test1, test2])
633 remote.add_url(test3)
634 self.assertEqual(list(remote.urls), [test1, test2, test3])
635 # Testing removing all the URLs
636 remote.delete_url(test2)
637 self.assertEqual(list(remote.urls), [test1, test3])
638 remote.delete_url(test1)
639 self.assertEqual(list(remote.urls), [test3])
640 # will raise fatal: Will not delete all non-push URLs
641 self.assertRaises(GitCommandError, remote.delete_url, test3)
642
643 def test_fetch_error(self):
644 rem = self.rorepo.remote('origin')
645 with self.assertRaisesRegex(GitCommandError, "[Cc]ouldn't find remote ref __BAD_REF__"):
646 rem.fetch('__BAD_REF__')
647
648 @with_rw_repo('0.1.6', bare=False)
649 def test_push_error(self, repo):
650 rem = repo.remote('origin')
651 with self.assertRaisesRegex(GitCommandError, "src refspec __BAD_REF__ does not match any"):
652 rem.push('__BAD_REF__')
+0
-1031
git/test/test_repo.py less more
0 # -*- coding: utf-8 -*-
1 # test_repo.py
2 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
3 #
4 # This module is part of GitPython and is released under
5 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
6 import glob
7 import io
8 from io import BytesIO
9 import itertools
10 import os
11 import pathlib
12 import pickle
13 import tempfile
14 from unittest import mock, skipIf, SkipTest
15
16 from git import (
17 InvalidGitRepositoryError,
18 Repo,
19 NoSuchPathError,
20 Head,
21 Commit,
22 Object,
23 Tree,
24 IndexFile,
25 Git,
26 Reference,
27 GitDB,
28 Submodule,
29 GitCmdObjectDB,
30 Remote,
31 BadName,
32 GitCommandError
33 )
34 from git.exc import (
35 BadObject,
36 )
37 from git.repo.fun import touch
38 from git.test.lib import (
39 TestBase,
40 with_rw_repo,
41 fixture
42 )
43 from git.util import HIDE_WINDOWS_KNOWN_ERRORS, cygpath
44 from git.test.lib import with_rw_directory
45 from git.util import join_path_native, rmtree, rmfile, bin_to_hex
46
47 import os.path as osp
48
49
50 def iter_flatten(lol):
51 for items in lol:
52 for item in items:
53 yield item
54
55
56 def flatten(lol):
57 return list(iter_flatten(lol))
58
59
60 _tc_lock_fpaths = osp.join(osp.dirname(__file__), '../../.git/*.lock')
61
62
63 def _rm_lock_files():
64 for lfp in glob.glob(_tc_lock_fpaths):
65 rmfile(lfp)
66
67
68 class TestRepo(TestBase):
69
70 def setUp(self):
71 _rm_lock_files()
72
73 def tearDown(self):
74 for lfp in glob.glob(_tc_lock_fpaths):
75 if osp.isfile(lfp):
76 raise AssertionError('Previous TC left hanging git-lock file: {}'.format(lfp))
77 import gc
78 gc.collect()
79
80 def test_new_should_raise_on_invalid_repo_location(self):
81 self.assertRaises(InvalidGitRepositoryError, Repo, tempfile.gettempdir())
82
83 def test_new_should_raise_on_non_existent_path(self):
84 self.assertRaises(NoSuchPathError, Repo, "repos/foobar")
85
86 @with_rw_repo('0.3.2.1')
87 def test_repo_creation_from_different_paths(self, rw_repo):
88 r_from_gitdir = Repo(rw_repo.git_dir)
89 self.assertEqual(r_from_gitdir.git_dir, rw_repo.git_dir)
90 assert r_from_gitdir.git_dir.endswith('.git')
91 assert not rw_repo.git.working_dir.endswith('.git')
92 self.assertEqual(r_from_gitdir.git.working_dir, rw_repo.git.working_dir)
93
94 @with_rw_repo('0.3.2.1')
95 def test_repo_creation_pathlib(self, rw_repo):
96 r_from_gitdir = Repo(pathlib.Path(rw_repo.git_dir))
97 self.assertEqual(r_from_gitdir.git_dir, rw_repo.git_dir)
98
99 def test_description(self):
100 txt = "Test repository"
101 self.rorepo.description = txt
102 self.assertEqual(self.rorepo.description, txt)
103
104 def test_heads_should_return_array_of_head_objects(self):
105 for head in self.rorepo.heads:
106 self.assertEqual(Head, head.__class__)
107
108 def test_heads_should_populate_head_data(self):
109 for head in self.rorepo.heads:
110 assert head.name
111 self.assertIsInstance(head.commit, Commit)
112 # END for each head
113
114 self.assertIsInstance(self.rorepo.heads.master, Head)
115 self.assertIsInstance(self.rorepo.heads['master'], Head)
116
117 def test_tree_from_revision(self):
118 tree = self.rorepo.tree('0.1.6')
119 self.assertEqual(len(tree.hexsha), 40)
120 self.assertEqual(tree.type, "tree")
121 self.assertEqual(self.rorepo.tree(tree), tree)
122
123 # try from invalid revision that does not exist
124 self.assertRaises(BadName, self.rorepo.tree, 'hello world')
125
126 def test_pickleable(self):
127 pickle.loads(pickle.dumps(self.rorepo))
128
129 def test_commit_from_revision(self):
130 commit = self.rorepo.commit('0.1.4')
131 self.assertEqual(commit.type, 'commit')
132 self.assertEqual(self.rorepo.commit(commit), commit)
133
134 def test_commits(self):
135 mc = 10
136 commits = list(self.rorepo.iter_commits('0.1.6', max_count=mc))
137 self.assertEqual(len(commits), mc)
138
139 c = commits[0]
140 self.assertEqual('9a4b1d4d11eee3c5362a4152216376e634bd14cf', c.hexsha)
141 self.assertEqual(["c76852d0bff115720af3f27acdb084c59361e5f6"], [p.hexsha for p in c.parents])
142 self.assertEqual("ce41fc29549042f1aa09cc03174896cf23f112e3", c.tree.hexsha)
143 self.assertEqual("Michael Trier", c.author.name)
144 self.assertEqual("mtrier@gmail.com", c.author.email)
145 self.assertEqual(1232829715, c.authored_date)
146 self.assertEqual(5 * 3600, c.author_tz_offset)
147 self.assertEqual("Michael Trier", c.committer.name)
148 self.assertEqual("mtrier@gmail.com", c.committer.email)
149 self.assertEqual(1232829715, c.committed_date)
150 self.assertEqual(5 * 3600, c.committer_tz_offset)
151 self.assertEqual("Bumped version 0.1.6\n", c.message)
152
153 c = commits[1]
154 self.assertIsInstance(c.parents, tuple)
155
156 def test_trees(self):
157 mc = 30
158 num_trees = 0
159 for tree in self.rorepo.iter_trees('0.1.5', max_count=mc):
160 num_trees += 1
161 self.assertIsInstance(tree, Tree)
162 # END for each tree
163 self.assertEqual(num_trees, mc)
164
165 def _assert_empty_repo(self, repo):
166 # test all kinds of things with an empty, freshly initialized repo.
167 # It should throw good errors
168
169 # entries should be empty
170 self.assertEqual(len(repo.index.entries), 0)
171
172 # head is accessible
173 assert repo.head
174 assert repo.head.ref
175 assert not repo.head.is_valid()
176
177 # we can change the head to some other ref
178 head_ref = Head.from_path(repo, Head.to_full_path('some_head'))
179 assert not head_ref.is_valid()
180 repo.head.ref = head_ref
181
182 # is_dirty can handle all kwargs
183 for args in ((1, 0, 0), (0, 1, 0), (0, 0, 1)):
184 assert not repo.is_dirty(*args)
185 # END for each arg
186
187 # we can add a file to the index ( if we are not bare )
188 if not repo.bare:
189 pass
190 # END test repos with working tree
191
192 @with_rw_directory
193 def test_clone_from_keeps_env(self, rw_dir):
194 original_repo = Repo.init(osp.join(rw_dir, "repo"))
195 environment = {"entry1": "value", "another_entry": "10"}
196
197 cloned = Repo.clone_from(original_repo.git_dir, osp.join(rw_dir, "clone"), env=environment)
198
199 self.assertEqual(environment, cloned.git.environment())
200
201 @with_rw_directory
202 def test_date_format(self, rw_dir):
203 repo = Repo.init(osp.join(rw_dir, "repo"))
204 # @-timestamp is the format used by git commit hooks
205 repo.index.commit("Commit messages", commit_date="@1400000000 +0000")
206
207 @with_rw_directory
208 def test_clone_from_pathlib(self, rw_dir):
209 original_repo = Repo.init(osp.join(rw_dir, "repo"))
210
211 Repo.clone_from(original_repo.git_dir, pathlib.Path(rw_dir) / "clone_pathlib")
212
213 @with_rw_directory
214 def test_clone_from_pathlib_withConfig(self, rw_dir):
215 original_repo = Repo.init(osp.join(rw_dir, "repo"))
216
217 cloned = Repo.clone_from(original_repo.git_dir, pathlib.Path(rw_dir) / "clone_pathlib_withConfig",
218 multi_options=["--recurse-submodules=repo",
219 "--config core.filemode=false",
220 "--config submodule.repo.update=checkout"])
221
222 self.assertEqual(cloned.config_reader().get_value('submodule', 'active'), 'repo')
223 self.assertEqual(cloned.config_reader().get_value('core', 'filemode'), False)
224 self.assertEqual(cloned.config_reader().get_value('submodule "repo"', 'update'), 'checkout')
225
226 def test_clone_from_with_path_contains_unicode(self):
227 with tempfile.TemporaryDirectory() as tmpdir:
228 unicode_dir_name = '\u0394'
229 path_with_unicode = os.path.join(tmpdir, unicode_dir_name)
230 os.makedirs(path_with_unicode)
231
232 try:
233 Repo.clone_from(
234 url=self._small_repo_url(),
235 to_path=path_with_unicode,
236 )
237 except UnicodeEncodeError:
238 self.fail('Raised UnicodeEncodeError')
239
240 @with_rw_repo('HEAD')
241 def test_max_chunk_size(self, repo):
242 class TestOutputStream(TestBase):
243 def __init__(self, max_chunk_size):
244 self.max_chunk_size = max_chunk_size
245
246 def write(self, b):
247 self.assertTrue(len(b) <= self.max_chunk_size)
248
249 for chunk_size in [16, 128, 1024]:
250 repo.git.status(output_stream=TestOutputStream(chunk_size), max_chunk_size=chunk_size)
251
252 repo.git.log(n=100, output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE), max_chunk_size=None)
253 repo.git.log(n=100, output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE), max_chunk_size=-10)
254 repo.git.log(n=100, output_stream=TestOutputStream(io.DEFAULT_BUFFER_SIZE))
255
256 def test_init(self):
257 prev_cwd = os.getcwd()
258 os.chdir(tempfile.gettempdir())
259 git_dir_rela = "repos/foo/bar.git"
260 del_dir_abs = osp.abspath("repos")
261 git_dir_abs = osp.abspath(git_dir_rela)
262 try:
263 # with specific path
264 for path in (git_dir_rela, git_dir_abs):
265 r = Repo.init(path=path, bare=True)
266 self.assertIsInstance(r, Repo)
267 assert r.bare is True
268 assert not r.has_separate_working_tree()
269 assert osp.isdir(r.git_dir)
270
271 self._assert_empty_repo(r)
272
273 # test clone
274 clone_path = path + "_clone"
275 rc = r.clone(clone_path)
276 self._assert_empty_repo(rc)
277
278 try:
279 rmtree(clone_path)
280 except OSError:
281 # when relative paths are used, the clone may actually be inside
282 # of the parent directory
283 pass
284 # END exception handling
285
286 # try again, this time with the absolute version
287 rc = Repo.clone_from(r.git_dir, clone_path)
288 self._assert_empty_repo(rc)
289
290 rmtree(git_dir_abs)
291 try:
292 rmtree(clone_path)
293 except OSError:
294 # when relative paths are used, the clone may actually be inside
295 # of the parent directory
296 pass
297 # END exception handling
298
299 # END for each path
300
301 os.makedirs(git_dir_rela)
302 os.chdir(git_dir_rela)
303 r = Repo.init(bare=False)
304 assert r.bare is False
305 assert not r.has_separate_working_tree()
306
307 self._assert_empty_repo(r)
308 finally:
309 try:
310 rmtree(del_dir_abs)
311 except OSError:
312 pass
313 os.chdir(prev_cwd)
314 # END restore previous state
315
316 def test_bare_property(self):
317 self.rorepo.bare
318
319 def test_daemon_export(self):
320 orig_val = self.rorepo.daemon_export
321 self.rorepo.daemon_export = not orig_val
322 self.assertEqual(self.rorepo.daemon_export, (not orig_val))
323 self.rorepo.daemon_export = orig_val
324 self.assertEqual(self.rorepo.daemon_export, orig_val)
325
326 def test_alternates(self):
327 cur_alternates = self.rorepo.alternates
328 # empty alternates
329 self.rorepo.alternates = []
330 self.assertEqual(self.rorepo.alternates, [])
331 alts = ["other/location", "this/location"]
332 self.rorepo.alternates = alts
333 self.assertEqual(alts, self.rorepo.alternates)
334 self.rorepo.alternates = cur_alternates
335
336 def test_repr(self):
337 assert repr(self.rorepo).startswith('<git.repo.base.Repo ')
338
339 def test_is_dirty_with_bare_repository(self):
340 orig_value = self.rorepo._bare
341 self.rorepo._bare = True
342 self.assertFalse(self.rorepo.is_dirty())
343 self.rorepo._bare = orig_value
344
345 def test_is_dirty(self):
346 self.rorepo._bare = False
347 for index in (0, 1):
348 for working_tree in (0, 1):
349 for untracked_files in (0, 1):
350 assert self.rorepo.is_dirty(index, working_tree, untracked_files) in (True, False)
351 # END untracked files
352 # END working tree
353 # END index
354 orig_val = self.rorepo._bare
355 self.rorepo._bare = True
356 assert self.rorepo.is_dirty() is False
357 self.rorepo._bare = orig_val
358
359 @with_rw_repo('HEAD')
360 def test_is_dirty_with_path(self, rwrepo):
361 assert rwrepo.is_dirty(path="git") is False
362
363 with open(osp.join(rwrepo.working_dir, "git", "util.py"), "at") as f:
364 f.write("junk")
365 assert rwrepo.is_dirty(path="git") is True
366 assert rwrepo.is_dirty(path="doc") is False
367
368 rwrepo.git.add(Git.polish_url(osp.join("git", "util.py")))
369 assert rwrepo.is_dirty(index=False, path="git") is False
370 assert rwrepo.is_dirty(path="git") is True
371
372 with open(osp.join(rwrepo.working_dir, "doc", "no-such-file.txt"), "wt") as f:
373 f.write("junk")
374 assert rwrepo.is_dirty(path="doc") is False
375 assert rwrepo.is_dirty(untracked_files=True, path="doc") is True
376
377 def test_head(self):
378 self.assertEqual(self.rorepo.head.reference.object, self.rorepo.active_branch.object)
379
380 def test_index(self):
381 index = self.rorepo.index
382 self.assertIsInstance(index, IndexFile)
383
384 def test_tag(self):
385 assert self.rorepo.tag('refs/tags/0.1.5').commit
386
387 def test_archive(self):
388 tmpfile = tempfile.mktemp(suffix='archive-test')
389 with open(tmpfile, 'wb') as stream:
390 self.rorepo.archive(stream, '0.1.6', path='doc')
391 assert stream.tell()
392 os.remove(tmpfile)
393
394 @mock.patch.object(Git, '_call_process')
395 def test_should_display_blame_information(self, git):
396 git.return_value = fixture('blame')
397 b = self.rorepo.blame('master', 'lib/git.py')
398 self.assertEqual(13, len(b))
399 self.assertEqual(2, len(b[0]))
400 # self.assertEqual(25, reduce(lambda acc, x: acc + len(x[-1]), b))
401 self.assertEqual(hash(b[0][0]), hash(b[9][0]))
402 c = b[0][0]
403 self.assertTrue(git.called)
404
405 self.assertEqual('634396b2f541a9f2d58b00be1a07f0c358b999b3', c.hexsha)
406 self.assertEqual('Tom Preston-Werner', c.author.name)
407 self.assertEqual('tom@mojombo.com', c.author.email)
408 self.assertEqual(1191997100, c.authored_date)
409 self.assertEqual('Tom Preston-Werner', c.committer.name)
410 self.assertEqual('tom@mojombo.com', c.committer.email)
411 self.assertEqual(1191997100, c.committed_date)
412 self.assertRaisesRegex(ValueError, "634396b2f541a9f2d58b00be1a07f0c358b999b3 missing", lambda: c.message)
413
414 # test the 'lines per commit' entries
415 tlist = b[0][1]
416 self.assertTrue(tlist)
417 self.assertTrue(isinstance(tlist[0], str))
418 self.assertTrue(len(tlist) < sum(len(t) for t in tlist)) # test for single-char bug
419
420 # BINARY BLAME
421 git.return_value = fixture('blame_binary')
422 blames = self.rorepo.blame('master', 'rps')
423 self.assertEqual(len(blames), 2)
424
425 def test_blame_real(self):
426 c = 0
427 nml = 0 # amount of multi-lines per blame
428 for item in self.rorepo.head.commit.tree.traverse(
429 predicate=lambda i, d: i.type == 'blob' and i.path.endswith('.py')):
430 c += 1
431
432 for b in self.rorepo.blame(self.rorepo.head, item.path):
433 nml += int(len(b[1]) > 1)
434 # END for each item to traverse
435 assert c, "Should have executed at least one blame command"
436 assert nml, "There should at least be one blame commit that contains multiple lines"
437
438 @mock.patch.object(Git, '_call_process')
439 def test_blame_incremental(self, git):
440 # loop over two fixtures, create a test fixture for 2.11.1+ syntax
441 for git_fixture in ('blame_incremental', 'blame_incremental_2.11.1_plus'):
442 git.return_value = fixture(git_fixture)
443 blame_output = self.rorepo.blame_incremental('9debf6b0aafb6f7781ea9d1383c86939a1aacde3', 'AUTHORS')
444 blame_output = list(blame_output)
445 self.assertEqual(len(blame_output), 5)
446
447 # Check all outputted line numbers
448 ranges = flatten([entry.linenos for entry in blame_output])
449 self.assertEqual(ranges, flatten([range(2, 3), range(14, 15), range(1, 2), range(3, 14), range(15, 17)]))
450
451 commits = [entry.commit.hexsha[:7] for entry in blame_output]
452 self.assertEqual(commits, ['82b8902', '82b8902', 'c76852d', 'c76852d', 'c76852d'])
453
454 # Original filenames
455 self.assertSequenceEqual([entry.orig_path for entry in blame_output], ['AUTHORS'] * len(blame_output))
456
457 # Original line numbers
458 orig_ranges = flatten([entry.orig_linenos for entry in blame_output])
459 self.assertEqual(orig_ranges, flatten([range(2, 3), range(14, 15), range(1, 2), range(2, 13), range(13, 15)])) # noqa E501
460
461 @mock.patch.object(Git, '_call_process')
462 def test_blame_complex_revision(self, git):
463 git.return_value = fixture('blame_complex_revision')
464 res = self.rorepo.blame("HEAD~10..HEAD", "README.md")
465 self.assertEqual(len(res), 1)
466 self.assertEqual(len(res[0][1]), 83, "Unexpected amount of parsed blame lines")
467
468 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and Git.is_cygwin(),
469 """FIXME: File "C:\\projects\\gitpython\\git\\cmd.py", line 671, in execute
470 raise GitCommandError(command, status, stderr_value, stdout_value)
471 GitCommandError: Cmd('git') failed due to: exit code(128)
472 cmdline: git add 1__��ava verb��ten 1_test _myfile 1_test_other_file
473 1_��ava-----verb��ten
474 stderr: 'fatal: pathspec '"1__çava verböten"' did not match any files'
475 """)
476 @with_rw_repo('HEAD', bare=False)
477 def test_untracked_files(self, rwrepo):
478 for run, repo_add in enumerate((rwrepo.index.add, rwrepo.git.add)):
479 base = rwrepo.working_tree_dir
480 files = (join_path_native(base, "%i_test _myfile" % run),
481 join_path_native(base, "%i_test_other_file" % run),
482 join_path_native(base, "%i__çava verböten" % run),
483 join_path_native(base, "%i_çava-----verböten" % run))
484
485 num_recently_untracked = 0
486 for fpath in files:
487 with open(fpath, "wb"):
488 pass
489 untracked_files = rwrepo.untracked_files
490 num_recently_untracked = len(untracked_files)
491
492 # assure we have all names - they are relative to the git-dir
493 num_test_untracked = 0
494 for utfile in untracked_files:
495 num_test_untracked += join_path_native(base, utfile) in files
496 self.assertEqual(len(files), num_test_untracked)
497
498 repo_add(untracked_files)
499 self.assertEqual(len(rwrepo.untracked_files), (num_recently_untracked - len(files)))
500 # end for each run
501
502 def test_config_reader(self):
503 reader = self.rorepo.config_reader() # all config files
504 assert reader.read_only
505 reader = self.rorepo.config_reader("repository") # single config file
506 assert reader.read_only
507
508 def test_config_writer(self):
509 for config_level in self.rorepo.config_level:
510 try:
511 with self.rorepo.config_writer(config_level) as writer:
512 self.assertFalse(writer.read_only)
513 except IOError:
514 # its okay not to get a writer for some configuration files if we
515 # have no permissions
516 pass
517
518 def test_config_level_paths(self):
519 for config_level in self.rorepo.config_level:
520 assert self.rorepo._get_config_path(config_level)
521
522 def test_creation_deletion(self):
523 # just a very quick test to assure it generally works. There are
524 # specialized cases in the test_refs module
525 head = self.rorepo.create_head("new_head", "HEAD~1")
526 self.rorepo.delete_head(head)
527
528 try:
529 tag = self.rorepo.create_tag("new_tag", "HEAD~2")
530 finally:
531 self.rorepo.delete_tag(tag)
532 with self.rorepo.config_writer():
533 pass
534 try:
535 remote = self.rorepo.create_remote("new_remote", "git@server:repo.git")
536 finally:
537 self.rorepo.delete_remote(remote)
538
539 def test_comparison_and_hash(self):
540 # this is only a preliminary test, more testing done in test_index
541 self.assertEqual(self.rorepo, self.rorepo)
542 self.assertFalse(self.rorepo != self.rorepo)
543 self.assertEqual(len({self.rorepo, self.rorepo}), 1)
544
545 @with_rw_directory
546 def test_tilde_and_env_vars_in_repo_path(self, rw_dir):
547 ph = os.environ.get('HOME')
548 try:
549 os.environ['HOME'] = rw_dir
550 Repo.init(osp.join('~', 'test.git'), bare=True)
551
552 os.environ['FOO'] = rw_dir
553 Repo.init(osp.join('$FOO', 'test.git'), bare=True)
554 finally:
555 if ph:
556 os.environ['HOME'] = ph
557 del os.environ['FOO']
558 # end assure HOME gets reset to what it was
559
560 def test_git_cmd(self):
561 # test CatFileContentStream, just to be very sure we have no fencepost errors
562 # last \n is the terminating newline that it expects
563 l1 = b"0123456789\n"
564 l2 = b"abcdefghijklmnopqrstxy\n"
565 l3 = b"z\n"
566 d = l1 + l2 + l3 + b"\n"
567
568 l1p = l1[:5]
569
570 # full size
571 # size is without terminating newline
572 def mkfull():
573 return Git.CatFileContentStream(len(d) - 1, BytesIO(d))
574
575 ts = 5
576
577 def mktiny():
578 return Git.CatFileContentStream(ts, BytesIO(d))
579
580 # readlines no limit
581 s = mkfull()
582 lines = s.readlines()
583 self.assertEqual(len(lines), 3)
584 self.assertTrue(lines[-1].endswith(b'\n'), lines[-1])
585 self.assertEqual(s._stream.tell(), len(d)) # must have scrubbed to the end
586
587 # realines line limit
588 s = mkfull()
589 lines = s.readlines(5)
590 self.assertEqual(len(lines), 1)
591
592 # readlines on tiny sections
593 s = mktiny()
594 lines = s.readlines()
595 self.assertEqual(len(lines), 1)
596 self.assertEqual(lines[0], l1p)
597 self.assertEqual(s._stream.tell(), ts + 1)
598
599 # readline no limit
600 s = mkfull()
601 self.assertEqual(s.readline(), l1)
602 self.assertEqual(s.readline(), l2)
603 self.assertEqual(s.readline(), l3)
604 self.assertEqual(s.readline(), b'')
605 self.assertEqual(s._stream.tell(), len(d))
606
607 # readline limit
608 s = mkfull()
609 self.assertEqual(s.readline(5), l1p)
610 self.assertEqual(s.readline(), l1[5:])
611
612 # readline on tiny section
613 s = mktiny()
614 self.assertEqual(s.readline(), l1p)
615 self.assertEqual(s.readline(), b'')
616 self.assertEqual(s._stream.tell(), ts + 1)
617
618 # read no limit
619 s = mkfull()
620 self.assertEqual(s.read(), d[:-1])
621 self.assertEqual(s.read(), b'')
622 self.assertEqual(s._stream.tell(), len(d))
623
624 # read limit
625 s = mkfull()
626 self.assertEqual(s.read(5), l1p)
627 self.assertEqual(s.read(6), l1[5:])
628 self.assertEqual(s._stream.tell(), 5 + 6) # its not yet done
629
630 # read tiny
631 s = mktiny()
632 self.assertEqual(s.read(2), l1[:2])
633 self.assertEqual(s._stream.tell(), 2)
634 self.assertEqual(s.read(), l1[2:ts])
635 self.assertEqual(s._stream.tell(), ts + 1)
636
637 def _assert_rev_parse_types(self, name, rev_obj):
638 rev_parse = self.rorepo.rev_parse
639
640 if rev_obj.type == 'tag':
641 rev_obj = rev_obj.object
642
643 # tree and blob type
644 obj = rev_parse(name + '^{tree}')
645 self.assertEqual(obj, rev_obj.tree)
646
647 obj = rev_parse(name + ':CHANGES')
648 self.assertEqual(obj.type, 'blob')
649 self.assertEqual(obj.path, 'CHANGES')
650 self.assertEqual(rev_obj.tree['CHANGES'], obj)
651
652 def _assert_rev_parse(self, name):
653 """tries multiple different rev-parse syntaxes with the given name
654 :return: parsed object"""
655 rev_parse = self.rorepo.rev_parse
656 orig_obj = rev_parse(name)
657 if orig_obj.type == 'tag':
658 obj = orig_obj.object
659 else:
660 obj = orig_obj
661 # END deref tags by default
662
663 # try history
664 rev = name + "~"
665 obj2 = rev_parse(rev)
666 self.assertEqual(obj2, obj.parents[0])
667 self._assert_rev_parse_types(rev, obj2)
668
669 # history with number
670 ni = 11
671 history = [obj.parents[0]]
672 for pn in range(ni):
673 history.append(history[-1].parents[0])
674 # END get given amount of commits
675
676 for pn in range(11):
677 rev = name + "~%i" % (pn + 1)
678 obj2 = rev_parse(rev)
679 self.assertEqual(obj2, history[pn])
680 self._assert_rev_parse_types(rev, obj2)
681 # END history check
682
683 # parent ( default )
684 rev = name + "^"
685 obj2 = rev_parse(rev)
686 self.assertEqual(obj2, obj.parents[0])
687 self._assert_rev_parse_types(rev, obj2)
688
689 # parent with number
690 for pn, parent in enumerate(obj.parents):
691 rev = name + "^%i" % (pn + 1)
692 self.assertEqual(rev_parse(rev), parent)
693 self._assert_rev_parse_types(rev, parent)
694 # END for each parent
695
696 return orig_obj
697
698 @with_rw_repo('HEAD', bare=False)
699 def test_rw_rev_parse(self, rwrepo):
700 # verify it does not confuse branches with hexsha ids
701 ahead = rwrepo.create_head('aaaaaaaa')
702 assert(rwrepo.rev_parse(str(ahead)) == ahead.commit)
703
704 def test_rev_parse(self):
705 rev_parse = self.rorepo.rev_parse
706
707 # try special case: This one failed at some point, make sure its fixed
708 self.assertEqual(rev_parse("33ebe").hexsha, "33ebe7acec14b25c5f84f35a664803fcab2f7781")
709
710 # start from reference
711 num_resolved = 0
712
713 for ref_no, ref in enumerate(Reference.iter_items(self.rorepo)):
714 path_tokens = ref.path.split("/")
715 for pt in range(len(path_tokens)):
716 path_section = '/'.join(path_tokens[-(pt + 1):])
717 try:
718 obj = self._assert_rev_parse(path_section)
719 self.assertEqual(obj.type, ref.object.type)
720 num_resolved += 1
721 except (BadName, BadObject):
722 print("failed on %s" % path_section)
723 # is fine, in case we have something like 112, which belongs to remotes/rname/merge-requests/112
724 # END exception handling
725 # END for each token
726 if ref_no == 3 - 1:
727 break
728 # END for each reference
729 assert num_resolved
730
731 # it works with tags !
732 tag = self._assert_rev_parse('0.1.4')
733 self.assertEqual(tag.type, 'tag')
734
735 # try full sha directly ( including type conversion )
736 self.assertEqual(tag.object, rev_parse(tag.object.hexsha))
737 self._assert_rev_parse_types(tag.object.hexsha, tag.object)
738
739 # multiple tree types result in the same tree: HEAD^{tree}^{tree}:CHANGES
740 rev = '0.1.4^{tree}^{tree}'
741 self.assertEqual(rev_parse(rev), tag.object.tree)
742 self.assertEqual(rev_parse(rev + ':CHANGES'), tag.object.tree['CHANGES'])
743
744 # try to get parents from first revision - it should fail as no such revision
745 # exists
746 first_rev = "33ebe7acec14b25c5f84f35a664803fcab2f7781"
747 commit = rev_parse(first_rev)
748 self.assertEqual(len(commit.parents), 0)
749 self.assertEqual(commit.hexsha, first_rev)
750 self.assertRaises(BadName, rev_parse, first_rev + "~")
751 self.assertRaises(BadName, rev_parse, first_rev + "^")
752
753 # short SHA1
754 commit2 = rev_parse(first_rev[:20])
755 self.assertEqual(commit2, commit)
756 commit2 = rev_parse(first_rev[:5])
757 self.assertEqual(commit2, commit)
758
759 # todo: dereference tag into a blob 0.1.7^{blob} - quite a special one
760 # needs a tag which points to a blob
761
762 # ref^0 returns commit being pointed to, same with ref~0, and ^{}
763 tag = rev_parse('0.1.4')
764 for token in (('~0', '^0', '^{}')):
765 self.assertEqual(tag.object, rev_parse('0.1.4%s' % token))
766 # END handle multiple tokens
767
768 # try partial parsing
769 max_items = 40
770 for i, binsha in enumerate(self.rorepo.odb.sha_iter()):
771 self.assertEqual(rev_parse(bin_to_hex(binsha)[:8 - (i % 2)].decode('ascii')).binsha, binsha)
772 if i > max_items:
773 # this is rather slow currently, as rev_parse returns an object
774 # which requires accessing packs, it has some additional overhead
775 break
776 # END for each binsha in repo
777
778 # missing closing brace commit^{tree
779 self.assertRaises(ValueError, rev_parse, '0.1.4^{tree')
780
781 # missing starting brace
782 self.assertRaises(ValueError, rev_parse, '0.1.4^tree}')
783
784 # REVLOG
785 #######
786 head = self.rorepo.head
787
788 # need to specify a ref when using the @ syntax
789 self.assertRaises(BadObject, rev_parse, "%s@{0}" % head.commit.hexsha)
790
791 # uses HEAD.ref by default
792 self.assertEqual(rev_parse('@{0}'), head.commit)
793 if not head.is_detached:
794 refspec = '%s@{0}' % head.ref.name
795 self.assertEqual(rev_parse(refspec), head.ref.commit)
796 # all additional specs work as well
797 self.assertEqual(rev_parse(refspec + "^{tree}"), head.commit.tree)
798 self.assertEqual(rev_parse(refspec + ":CHANGES").type, 'blob')
799 # END operate on non-detached head
800
801 # position doesn't exist
802 self.assertRaises(IndexError, rev_parse, '@{10000}')
803
804 # currently, nothing more is supported
805 self.assertRaises(NotImplementedError, rev_parse, "@{1 week ago}")
806
807 # the last position
808 assert rev_parse('@{1}') != head.commit
809
810 def test_repo_odbtype(self):
811 target_type = GitCmdObjectDB
812 self.assertIsInstance(self.rorepo.odb, target_type)
813
814 def test_submodules(self):
815 self.assertEqual(len(self.rorepo.submodules), 1) # non-recursive
816 self.assertGreaterEqual(len(list(self.rorepo.iter_submodules())), 2)
817
818 self.assertIsInstance(self.rorepo.submodule("gitdb"), Submodule)
819 self.assertRaises(ValueError, self.rorepo.submodule, "doesn't exist")
820
821 @with_rw_repo('HEAD', bare=False)
822 def test_submodule_update(self, rwrepo):
823 # fails in bare mode
824 rwrepo._bare = True
825 self.assertRaises(InvalidGitRepositoryError, rwrepo.submodule_update)
826 rwrepo._bare = False
827
828 # test create submodule
829 sm = rwrepo.submodules[0]
830 sm = rwrepo.create_submodule("my_new_sub", "some_path", join_path_native(self.rorepo.working_tree_dir, sm.path))
831 self.assertIsInstance(sm, Submodule)
832
833 # note: the rest of this functionality is tested in test_submodule
834
835 @with_rw_repo('HEAD')
836 def test_git_file(self, rwrepo):
837 # Move the .git directory to another location and create the .git file.
838 real_path_abs = osp.abspath(join_path_native(rwrepo.working_tree_dir, '.real'))
839 os.rename(rwrepo.git_dir, real_path_abs)
840 git_file_path = join_path_native(rwrepo.working_tree_dir, '.git')
841 with open(git_file_path, 'wb') as fp:
842 fp.write(fixture('git_file'))
843
844 # Create a repo and make sure it's pointing to the relocated .git directory.
845 git_file_repo = Repo(rwrepo.working_tree_dir)
846 self.assertEqual(osp.abspath(git_file_repo.git_dir), real_path_abs)
847
848 # Test using an absolute gitdir path in the .git file.
849 with open(git_file_path, 'wb') as fp:
850 fp.write(('gitdir: %s\n' % real_path_abs).encode('ascii'))
851 git_file_repo = Repo(rwrepo.working_tree_dir)
852 self.assertEqual(osp.abspath(git_file_repo.git_dir), real_path_abs)
853
854 def test_file_handle_leaks(self):
855 def last_commit(repo, rev, path):
856 commit = next(repo.iter_commits(rev, path, max_count=1))
857 commit.tree[path]
858
859 # This is based on this comment
860 # https://github.com/gitpython-developers/GitPython/issues/60#issuecomment-23558741
861 # And we expect to set max handles to a low value, like 64
862 # You should set ulimit -n X, see .travis.yml
863 # The loops below would easily create 500 handles if these would leak (4 pipes + multiple mapped files)
864 for _ in range(64):
865 for repo_type in (GitCmdObjectDB, GitDB):
866 repo = Repo(self.rorepo.working_tree_dir, odbt=repo_type)
867 last_commit(repo, 'master', 'git/test/test_base.py')
868 # end for each repository type
869 # end for each iteration
870
871 def test_remote_method(self):
872 self.assertRaises(ValueError, self.rorepo.remote, 'foo-blue')
873 self.assertIsInstance(self.rorepo.remote(name='origin'), Remote)
874
875 @with_rw_directory
876 def test_empty_repo(self, rw_dir):
877 """Assure we can handle empty repositories"""
878 r = Repo.init(rw_dir, mkdir=False)
879 # It's ok not to be able to iterate a commit, as there is none
880 self.assertRaises(ValueError, r.iter_commits)
881 self.assertEqual(r.active_branch.name, 'master')
882 assert not r.active_branch.is_valid(), "Branch is yet to be born"
883
884 # actually, when trying to create a new branch without a commit, git itself fails
885 # We should, however, not fail ungracefully
886 self.assertRaises(BadName, r.create_head, 'foo')
887 self.assertRaises(BadName, r.create_head, 'master')
888 # It's expected to not be able to access a tree
889 self.assertRaises(ValueError, r.tree)
890
891 new_file_path = osp.join(rw_dir, "new_file.ext")
892 touch(new_file_path)
893 r.index.add([new_file_path])
894 r.index.commit("initial commit\nBAD MESSAGE 1\n")
895
896 # Now a branch should be creatable
897 nb = r.create_head('foo')
898 assert nb.is_valid()
899
900 with open(new_file_path, 'w') as f:
901 f.write('Line 1\n')
902
903 r.index.add([new_file_path])
904 r.index.commit("add line 1\nBAD MESSAGE 2\n")
905
906 with open('%s/.git/logs/refs/heads/master' % (rw_dir,), 'r') as f:
907 contents = f.read()
908
909 assert 'BAD MESSAGE' not in contents, 'log is corrupt'
910
911 def test_merge_base(self):
912 repo = self.rorepo
913 c1 = 'f6aa8d1'
914 c2 = repo.commit('d46e3fe')
915 c3 = '763ef75'
916 self.assertRaises(ValueError, repo.merge_base)
917 self.assertRaises(ValueError, repo.merge_base, 'foo')
918
919 # two commit merge-base
920 res = repo.merge_base(c1, c2)
921 self.assertIsInstance(res, list)
922 self.assertEqual(len(res), 1)
923 self.assertIsInstance(res[0], Commit)
924 self.assertTrue(res[0].hexsha.startswith('3936084'))
925
926 for kw in ('a', 'all'):
927 res = repo.merge_base(c1, c2, c3, **{kw: True})
928 self.assertIsInstance(res, list)
929 self.assertEqual(len(res), 1)
930 # end for each keyword signalling all merge-bases to be returned
931
932 # Test for no merge base - can't do as we have
933 self.assertRaises(GitCommandError, repo.merge_base, c1, 'ffffff')
934
935 def test_is_ancestor(self):
936 git = self.rorepo.git
937 if git.version_info[:3] < (1, 8, 0):
938 raise SkipTest("git merge-base --is-ancestor feature unsupported")
939
940 repo = self.rorepo
941 c1 = 'f6aa8d1'
942 c2 = '763ef75'
943 self.assertTrue(repo.is_ancestor(c1, c1))
944 self.assertTrue(repo.is_ancestor("master", "master"))
945 self.assertTrue(repo.is_ancestor(c1, c2))
946 self.assertTrue(repo.is_ancestor(c1, "master"))
947 self.assertFalse(repo.is_ancestor(c2, c1))
948 self.assertFalse(repo.is_ancestor("master", c1))
949 for i, j in itertools.permutations([c1, 'ffffff', ''], r=2):
950 self.assertRaises(GitCommandError, repo.is_ancestor, i, j)
951
952 @with_rw_directory
953 def test_git_work_tree_dotgit(self, rw_dir):
954 """Check that we find .git as a worktree file and find the worktree
955 based on it."""
956 git = Git(rw_dir)
957 if git.version_info[:3] < (2, 5, 1):
958 raise SkipTest("worktree feature unsupported")
959
960 rw_master = self.rorepo.clone(join_path_native(rw_dir, 'master_repo'))
961 branch = rw_master.create_head('aaaaaaaa')
962 worktree_path = join_path_native(rw_dir, 'worktree_repo')
963 if Git.is_cygwin():
964 worktree_path = cygpath(worktree_path)
965 rw_master.git.worktree('add', worktree_path, branch.name)
966
967 # this ensures that we can read the repo's gitdir correctly
968 repo = Repo(worktree_path)
969 self.assertIsInstance(repo, Repo)
970
971 # this ensures we're able to actually read the refs in the tree, which
972 # means we can read commondir correctly.
973 commit = repo.head.commit
974 self.assertIsInstance(commit, Object)
975
976 # this ensures we can read the remotes, which confirms we're reading
977 # the config correctly.
978 origin = repo.remotes.origin
979 self.assertIsInstance(origin, Remote)
980
981 self.assertIsInstance(repo.heads['aaaaaaaa'], Head)
982
983 @with_rw_directory
984 def test_git_work_tree_env(self, rw_dir):
985 """Check that we yield to GIT_WORK_TREE"""
986 # clone a repo
987 # move .git directory to a subdirectory
988 # set GIT_DIR and GIT_WORK_TREE appropriately
989 # check that repo.working_tree_dir == rw_dir
990 self.rorepo.clone(join_path_native(rw_dir, 'master_repo'))
991
992 repo_dir = join_path_native(rw_dir, 'master_repo')
993 old_git_dir = join_path_native(repo_dir, '.git')
994 new_subdir = join_path_native(repo_dir, 'gitdir')
995 new_git_dir = join_path_native(new_subdir, 'git')
996 os.mkdir(new_subdir)
997 os.rename(old_git_dir, new_git_dir)
998
999 oldenv = os.environ.copy()
1000 os.environ['GIT_DIR'] = new_git_dir
1001 os.environ['GIT_WORK_TREE'] = repo_dir
1002
1003 try:
1004 r = Repo()
1005 self.assertEqual(r.working_tree_dir, repo_dir)
1006 self.assertEqual(r.working_dir, repo_dir)
1007 finally:
1008 os.environ = oldenv
1009
1010 @with_rw_directory
1011 def test_rebasing(self, rw_dir):
1012 r = Repo.init(rw_dir)
1013 fp = osp.join(rw_dir, 'hello.txt')
1014 r.git.commit("--allow-empty", message="init",)
1015 with open(fp, 'w') as fs:
1016 fs.write("hello world")
1017 r.git.add(Git.polish_url(fp))
1018 r.git.commit(message="English")
1019 self.assertEqual(r.currently_rebasing_on(), None)
1020 r.git.checkout("HEAD^1")
1021 with open(fp, 'w') as fs:
1022 fs.write("Hola Mundo")
1023 r.git.add(Git.polish_url(fp))
1024 r.git.commit(message="Spanish")
1025 commitSpanish = r.commit()
1026 try:
1027 r.git.rebase("master")
1028 except GitCommandError:
1029 pass
1030 self.assertEqual(r.currently_rebasing_on(), commitSpanish)
+0
-30
git/test/test_stats.py less more
0 # test_stats.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5
6 from git.test.lib import (
7 TestBase,
8 fixture
9 )
10 from git import Stats
11 from git.compat import defenc
12
13
14 class TestStats(TestBase):
15
16 def test_list_from_string(self):
17 output = fixture('diff_numstat').decode(defenc)
18 stats = Stats._list_from_string(self.rorepo, output)
19
20 self.assertEqual(2, stats.total['files'])
21 self.assertEqual(52, stats.total['lines'])
22 self.assertEqual(29, stats.total['insertions'])
23 self.assertEqual(23, stats.total['deletions'])
24
25 self.assertEqual(29, stats.files["a.txt"]['insertions'])
26 self.assertEqual(18, stats.files["a.txt"]['deletions'])
27
28 self.assertEqual(0, stats.files["b.txt"]['insertions'])
29 self.assertEqual(5, stats.files["b.txt"]['deletions'])
+0
-947
git/test/test_submodule.py less more
0 # -*- coding: utf-8 -*-
1 # This module is part of GitPython and is released under
2 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
3 import os
4 import shutil
5 import sys
6 from unittest import skipIf
7
8 import git
9 from git.cmd import Git
10 from git.compat import is_win
11 from git.exc import (
12 InvalidGitRepositoryError,
13 RepositoryDirtyError
14 )
15 from git.objects.submodule.base import Submodule
16 from git.objects.submodule.root import RootModule, RootUpdateProgress
17 from git.repo.fun import (
18 find_submodule_git_dir,
19 touch
20 )
21 from git.test.lib import (
22 TestBase,
23 with_rw_repo
24 )
25 from git.test.lib import with_rw_directory
26 from git.util import HIDE_WINDOWS_KNOWN_ERRORS
27 from git.util import to_native_path_linux, join_path_native
28 import os.path as osp
29
30
31 class TestRootProgress(RootUpdateProgress):
32 """Just prints messages, for now without checking the correctness of the states"""
33
34 def update(self, op, cur_count, max_count, message=''):
35 print(op, cur_count, max_count, message)
36
37
38 prog = TestRootProgress()
39
40
41 class TestSubmodule(TestBase):
42
43 def tearDown(self):
44 import gc
45 gc.collect()
46
47 k_subm_current = "c15a6e1923a14bc760851913858a3942a4193cdb"
48 k_subm_changed = "394ed7006ee5dc8bddfd132b64001d5dfc0ffdd3"
49 k_no_subm_tag = "0.1.6"
50
51 def _do_base_tests(self, rwrepo):
52 """Perform all tests in the given repository, it may be bare or nonbare"""
53 # manual instantiation
54 smm = Submodule(rwrepo, "\0" * 20)
55 # name needs to be set in advance
56 self.assertRaises(AttributeError, getattr, smm, 'name')
57
58 # iterate - 1 submodule
59 sms = Submodule.list_items(rwrepo, self.k_subm_current)
60 assert len(sms) == 1
61 sm = sms[0]
62
63 # at a different time, there is None
64 assert len(Submodule.list_items(rwrepo, self.k_no_subm_tag)) == 0
65
66 assert sm.path == 'git/ext/gitdb'
67 assert sm.path != sm.name # in our case, we have ids there, which don't equal the path
68 assert sm.url.endswith('github.com/gitpython-developers/gitdb.git')
69 assert sm.branch_path == 'refs/heads/master' # the default ...
70 assert sm.branch_name == 'master'
71 assert sm.parent_commit == rwrepo.head.commit
72 # size is always 0
73 assert sm.size == 0
74 # the module is not checked-out yet
75 self.assertRaises(InvalidGitRepositoryError, sm.module)
76
77 # which is why we can't get the branch either - it points into the module() repository
78 self.assertRaises(InvalidGitRepositoryError, getattr, sm, 'branch')
79
80 # branch_path works, as its just a string
81 assert isinstance(sm.branch_path, str)
82
83 # some commits earlier we still have a submodule, but its at a different commit
84 smold = next(Submodule.iter_items(rwrepo, self.k_subm_changed))
85 assert smold.binsha != sm.binsha
86 assert smold != sm # the name changed
87
88 # force it to reread its information
89 del(smold._url)
90 smold.url == sm.url # @NoEffect
91
92 # test config_reader/writer methods
93 sm.config_reader()
94 new_smclone_path = None # keep custom paths for later
95 new_csmclone_path = None #
96 if rwrepo.bare:
97 with self.assertRaises(InvalidGitRepositoryError):
98 with sm.config_writer() as cw:
99 pass
100 else:
101 with sm.config_writer() as writer:
102 # for faster checkout, set the url to the local path
103 new_smclone_path = Git.polish_url(osp.join(self.rorepo.working_tree_dir, sm.path))
104 writer.set_value('url', new_smclone_path)
105 writer.release()
106 assert sm.config_reader().get_value('url') == new_smclone_path
107 assert sm.url == new_smclone_path
108 # END handle bare repo
109 smold.config_reader()
110
111 # cannot get a writer on historical submodules
112 if not rwrepo.bare:
113 with self.assertRaises(ValueError):
114 with smold.config_writer():
115 pass
116 # END handle bare repo
117
118 # make the old into a new - this doesn't work as the name changed
119 self.assertRaises(ValueError, smold.set_parent_commit, self.k_subm_current)
120 # the sha is properly updated
121 smold.set_parent_commit(self.k_subm_changed + "~1")
122 assert smold.binsha != sm.binsha
123
124 # raises if the sm didn't exist in new parent - it keeps its
125 # parent_commit unchanged
126 self.assertRaises(ValueError, smold.set_parent_commit, self.k_no_subm_tag)
127
128 # TEST TODO: if a path in the gitmodules file, but not in the index, it raises
129
130 # TEST UPDATE
131 ##############
132 # module retrieval is not always possible
133 if rwrepo.bare:
134 self.assertRaises(InvalidGitRepositoryError, sm.module)
135 self.assertRaises(InvalidGitRepositoryError, sm.remove)
136 self.assertRaises(InvalidGitRepositoryError, sm.add, rwrepo, 'here', 'there')
137 else:
138 # its not checked out in our case
139 self.assertRaises(InvalidGitRepositoryError, sm.module)
140 assert not sm.module_exists()
141
142 # currently there is only one submodule
143 assert len(list(rwrepo.iter_submodules())) == 1
144 assert sm.binsha != "\0" * 20
145
146 # TEST ADD
147 ###########
148 # preliminary tests
149 # adding existing returns exactly the existing
150 sma = Submodule.add(rwrepo, sm.name, sm.path)
151 assert sma.path == sm.path
152
153 # no url and no module at path fails
154 self.assertRaises(ValueError, Submodule.add, rwrepo, "newsubm", "pathtorepo", url=None)
155
156 # CONTINUE UPDATE
157 #################
158
159 # lets update it - its a recursive one too
160 newdir = osp.join(sm.abspath, 'dir')
161 os.makedirs(newdir)
162
163 # update fails if the path already exists non-empty
164 self.assertRaises(OSError, sm.update)
165 os.rmdir(newdir)
166
167 # dry-run does nothing
168 sm.update(dry_run=True, progress=prog)
169 assert not sm.module_exists()
170
171 assert sm.update() is sm
172 sm_repopath = sm.path # cache for later
173 assert sm.module_exists()
174 assert isinstance(sm.module(), git.Repo)
175 assert sm.module().working_tree_dir == sm.abspath
176
177 # INTERLEAVE ADD TEST
178 #####################
179 # url must match the one in the existing repository ( if submodule name suggests a new one )
180 # or we raise
181 self.assertRaises(ValueError, Submodule.add, rwrepo, "newsubm", sm.path, "git://someurl/repo.git")
182
183 # CONTINUE UPDATE
184 #################
185 # we should have setup a tracking branch, which is also active
186 assert sm.module().head.ref.tracking_branch() is not None
187
188 # delete the whole directory and re-initialize
189 assert len(sm.children()) != 0
190 # shutil.rmtree(sm.abspath)
191 sm.remove(force=True, configuration=False)
192 assert len(sm.children()) == 0
193 # dry-run does nothing
194 sm.update(dry_run=True, recursive=False, progress=prog)
195 assert len(sm.children()) == 0
196
197 sm.update(recursive=False)
198 assert len(list(rwrepo.iter_submodules())) == 2
199 assert len(sm.children()) == 1 # its not checked out yet
200 csm = sm.children()[0]
201 assert not csm.module_exists()
202 csm_repopath = csm.path
203
204 # adjust the path of the submodules module to point to the local destination
205 new_csmclone_path = Git.polish_url(osp.join(self.rorepo.working_tree_dir, sm.path, csm.path))
206 with csm.config_writer() as writer:
207 writer.set_value('url', new_csmclone_path)
208 assert csm.url == new_csmclone_path
209
210 # dry-run does nothing
211 assert not csm.module_exists()
212 sm.update(recursive=True, dry_run=True, progress=prog)
213 assert not csm.module_exists()
214
215 # update recursively again
216 sm.update(recursive=True)
217 assert csm.module_exists()
218
219 # tracking branch once again
220 csm.module().head.ref.tracking_branch() is not None # @NoEffect
221
222 # this flushed in a sub-submodule
223 assert len(list(rwrepo.iter_submodules())) == 2
224
225 # reset both heads to the previous version, verify that to_latest_revision works
226 smods = (sm.module(), csm.module())
227 for repo in smods:
228 repo.head.reset('HEAD~2', working_tree=1)
229 # END for each repo to reset
230
231 # dry run does nothing
232 self.assertRaises(RepositoryDirtyError, sm.update, recursive=True, dry_run=True, progress=prog)
233 sm.update(recursive=True, dry_run=True, progress=prog, force=True)
234 for repo in smods:
235 assert repo.head.commit != repo.head.ref.tracking_branch().commit
236 # END for each repo to check
237
238 self.assertRaises(RepositoryDirtyError, sm.update, recursive=True, to_latest_revision=True)
239 sm.update(recursive=True, to_latest_revision=True, force=True)
240 for repo in smods:
241 assert repo.head.commit == repo.head.ref.tracking_branch().commit
242 # END for each repo to check
243 del(smods)
244
245 # if the head is detached, it still works ( but warns )
246 smref = sm.module().head.ref
247 sm.module().head.ref = 'HEAD~1'
248 # if there is no tracking branch, we get a warning as well
249 csm_tracking_branch = csm.module().head.ref.tracking_branch()
250 csm.module().head.ref.set_tracking_branch(None)
251 sm.update(recursive=True, to_latest_revision=True)
252
253 # to_latest_revision changes the child submodule's commit, it needs an
254 # update now
255 csm.set_parent_commit(csm.repo.head.commit)
256
257 # undo the changes
258 sm.module().head.ref = smref
259 csm.module().head.ref.set_tracking_branch(csm_tracking_branch)
260
261 # REMOVAL OF REPOSITOTRY
262 ########################
263 # must delete something
264 self.assertRaises(ValueError, csm.remove, module=False, configuration=False)
265
266 # module() is supposed to point to gitdb, which has a child-submodule whose URL is still pointing
267 # to GitHub. To save time, we will change it to
268 csm.set_parent_commit(csm.repo.head.commit)
269 with csm.config_writer() as cw:
270 cw.set_value('url', self._small_repo_url())
271 csm.repo.index.commit("adjusted URL to point to local source, instead of the internet")
272
273 # We have modified the configuration, hence the index is dirty, and the
274 # deletion will fail
275 # NOTE: As we did a few updates in the meanwhile, the indices were reset
276 # Hence we create some changes
277 csm.set_parent_commit(csm.repo.head.commit)
278 with sm.config_writer() as writer:
279 writer.set_value("somekey", "somevalue")
280 with csm.config_writer() as writer:
281 writer.set_value("okey", "ovalue")
282 self.assertRaises(InvalidGitRepositoryError, sm.remove)
283 # if we remove the dirty index, it would work
284 sm.module().index.reset()
285 # still, we have the file modified
286 self.assertRaises(InvalidGitRepositoryError, sm.remove, dry_run=True)
287 sm.module().index.reset(working_tree=True)
288
289 # enforce the submodule to be checked out at the right spot as well.
290 csm.update()
291 assert csm.module_exists()
292 assert csm.exists()
293 assert osp.isdir(csm.module().working_tree_dir)
294
295 # this would work
296 assert sm.remove(force=True, dry_run=True) is sm
297 assert sm.module_exists()
298 sm.remove(force=True, dry_run=True)
299 assert sm.module_exists()
300
301 # but ... we have untracked files in the child submodule
302 fn = join_path_native(csm.module().working_tree_dir, "newfile")
303 with open(fn, 'w') as fd:
304 fd.write("hi")
305 self.assertRaises(InvalidGitRepositoryError, sm.remove)
306
307 # forcibly delete the child repository
308 prev_count = len(sm.children())
309 self.assertRaises(ValueError, csm.remove, force=True)
310 # We removed sm, which removed all submodules. However, the instance we
311 # have still points to the commit prior to that, where it still existed
312 csm.set_parent_commit(csm.repo.commit(), check=False)
313 assert not csm.exists()
314 assert not csm.module_exists()
315 assert len(sm.children()) == prev_count
316 # now we have a changed index, as configuration was altered.
317 # fix this
318 sm.module().index.reset(working_tree=True)
319
320 # now delete only the module of the main submodule
321 assert sm.module_exists()
322 sm.remove(configuration=False, force=True)
323 assert sm.exists()
324 assert not sm.module_exists()
325 assert sm.config_reader().get_value('url')
326
327 # delete the rest
328 sm_path = sm.path
329 sm.remove()
330 assert not sm.exists()
331 assert not sm.module_exists()
332 self.assertRaises(ValueError, getattr, sm, 'path')
333
334 assert len(rwrepo.submodules) == 0
335
336 # ADD NEW SUBMODULE
337 ###################
338 # add a simple remote repo - trailing slashes are no problem
339 smid = "newsub"
340 osmid = "othersub"
341 nsm = Submodule.add(rwrepo, smid, sm_repopath, new_smclone_path + "/", None, no_checkout=True)
342 assert nsm.name == smid
343 assert nsm.module_exists()
344 assert nsm.exists()
345 # its not checked out
346 assert not osp.isfile(join_path_native(nsm.module().working_tree_dir, Submodule.k_modules_file))
347 assert len(rwrepo.submodules) == 1
348
349 # add another submodule, but into the root, not as submodule
350 osm = Submodule.add(rwrepo, osmid, csm_repopath, new_csmclone_path, Submodule.k_head_default)
351 assert osm != nsm
352 assert osm.module_exists()
353 assert osm.exists()
354 assert osp.isfile(join_path_native(osm.module().working_tree_dir, 'setup.py'))
355
356 assert len(rwrepo.submodules) == 2
357
358 # commit the changes, just to finalize the operation
359 rwrepo.index.commit("my submod commit")
360 assert len(rwrepo.submodules) == 2
361
362 # needs update as the head changed, it thinks its in the history
363 # of the repo otherwise
364 nsm.set_parent_commit(rwrepo.head.commit)
365 osm.set_parent_commit(rwrepo.head.commit)
366
367 # MOVE MODULE
368 #############
369 # invalid input
370 self.assertRaises(ValueError, nsm.move, 'doesntmatter', module=False, configuration=False)
371
372 # renaming to the same path does nothing
373 assert nsm.move(sm_path) is nsm
374
375 # rename a module
376 nmp = join_path_native("new", "module", "dir") + "/" # new module path
377 pmp = nsm.path
378 assert nsm.move(nmp) is nsm
379 nmp = nmp[:-1] # cut last /
380 nmpl = to_native_path_linux(nmp)
381 assert nsm.path == nmpl
382 assert rwrepo.submodules[0].path == nmpl
383
384 mpath = 'newsubmodule'
385 absmpath = join_path_native(rwrepo.working_tree_dir, mpath)
386 open(absmpath, 'w').write('')
387 self.assertRaises(ValueError, nsm.move, mpath)
388 os.remove(absmpath)
389
390 # now it works, as we just move it back
391 nsm.move(pmp)
392 assert nsm.path == pmp
393 assert rwrepo.submodules[0].path == pmp
394
395 # REMOVE 'EM ALL
396 ################
397 # if a submodule's repo has no remotes, it can't be added without an explicit url
398 osmod = osm.module()
399
400 osm.remove(module=False)
401 for remote in osmod.remotes:
402 remote.remove(osmod, remote.name)
403 assert not osm.exists()
404 self.assertRaises(ValueError, Submodule.add, rwrepo, osmid, csm_repopath, url=None)
405 # END handle bare mode
406
407 # Error if there is no submodule file here
408 self.assertRaises(IOError, Submodule._config_parser, rwrepo, rwrepo.commit(self.k_no_subm_tag), True)
409
410 # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, ## ACTUALLY skipped by `git.submodule.base#L869`.
411 # "FIXME: fails with: PermissionError: [WinError 32] The process cannot access the file because"
412 # "it is being used by another process: "
413 # "'C:\\Users\\ankostis\\AppData\\Local\\Temp\\tmp95c3z83bnon_bare_test_base_rw\\git\\ext\\gitdb\\gitdb\\ext\\smmap'") # noqa E501
414 @with_rw_repo(k_subm_current)
415 def test_base_rw(self, rwrepo):
416 self._do_base_tests(rwrepo)
417
418 @with_rw_repo(k_subm_current, bare=True)
419 def test_base_bare(self, rwrepo):
420 self._do_base_tests(rwrepo)
421
422 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and sys.version_info[:2] == (3, 5), """
423 File "C:\\projects\\gitpython\\git\\cmd.py", line 559, in execute
424 raise GitCommandNotFound(command, err)
425 git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
426 cmdline: git clone -n --shared -v C:\\projects\\gitpython\\.git Users\\appveyor\\AppData\\Local\\Temp\\1\\tmplyp6kr_rnon_bare_test_root_module""") # noqa E501
427 @with_rw_repo(k_subm_current, bare=False)
428 def test_root_module(self, rwrepo):
429 # Can query everything without problems
430 rm = RootModule(self.rorepo)
431 assert rm.module() is self.rorepo
432
433 # try attributes
434 rm.binsha
435 rm.mode
436 rm.path
437 assert rm.name == rm.k_root_name
438 assert rm.parent_commit == self.rorepo.head.commit
439 rm.url
440 rm.branch
441
442 assert len(rm.list_items(rm.module())) == 1
443 rm.config_reader()
444 with rm.config_writer():
445 pass
446
447 # deep traversal gitdb / async
448 rsmsp = [sm.path for sm in rm.traverse()]
449 assert len(rsmsp) >= 2 # gitdb and async [and smmap], async being a child of gitdb
450
451 # cannot set the parent commit as root module's path didn't exist
452 self.assertRaises(ValueError, rm.set_parent_commit, 'HEAD')
453
454 # TEST UPDATE
455 #############
456 # setup commit which remove existing, add new and modify existing submodules
457 rm = RootModule(rwrepo)
458 assert len(rm.children()) == 1
459
460 # modify path without modifying the index entry
461 # ( which is what the move method would do properly )
462 #==================================================
463 sm = rm.children()[0]
464 pp = "path/prefix"
465 fp = join_path_native(pp, sm.path)
466 prep = sm.path
467 assert not sm.module_exists() # was never updated after rwrepo's clone
468
469 # assure we clone from a local source
470 with sm.config_writer() as writer:
471 writer.set_value('url', Git.polish_url(osp.join(self.rorepo.working_tree_dir, sm.path)))
472
473 # dry-run does nothing
474 sm.update(recursive=False, dry_run=True, progress=prog)
475 assert not sm.module_exists()
476
477 sm.update(recursive=False)
478 assert sm.module_exists()
479 with sm.config_writer() as writer:
480 writer.set_value('path', fp) # change path to something with prefix AFTER url change
481
482 # update doesn't fail, because list_items ignores the wrong path in such situations.
483 rm.update(recursive=False)
484
485 # move it properly - doesn't work as it its path currently points to an indexentry
486 # which doesn't exist ( move it to some path, it doesn't matter here )
487 self.assertRaises(InvalidGitRepositoryError, sm.move, pp)
488 # reset the path(cache) to where it was, now it works
489 sm.path = prep
490 sm.move(fp, module=False) # leave it at the old location
491
492 assert not sm.module_exists()
493 cpathchange = rwrepo.index.commit("changed sm path") # finally we can commit
494
495 # update puts the module into place
496 rm.update(recursive=False, progress=prog)
497 sm.set_parent_commit(cpathchange)
498 assert sm.module_exists()
499
500 # add submodule
501 #================
502 nsmn = "newsubmodule"
503 nsmp = "submrepo"
504 subrepo_url = Git.polish_url(osp.join(self.rorepo.working_tree_dir, rsmsp[0], rsmsp[1]))
505 nsm = Submodule.add(rwrepo, nsmn, nsmp, url=subrepo_url)
506 csmadded = rwrepo.index.commit("Added submodule").hexsha # make sure we don't keep the repo reference
507 nsm.set_parent_commit(csmadded)
508 assert nsm.module_exists()
509 # in our case, the module should not exist, which happens if we update a parent
510 # repo and a new submodule comes into life
511 nsm.remove(configuration=False, module=True)
512 assert not nsm.module_exists() and nsm.exists()
513
514 # dry-run does nothing
515 rm.update(recursive=False, dry_run=True, progress=prog)
516
517 # otherwise it will work
518 rm.update(recursive=False, progress=prog)
519 assert nsm.module_exists()
520
521 # remove submodule - the previous one
522 #====================================
523 sm.set_parent_commit(csmadded)
524 smp = sm.abspath
525 assert not sm.remove(module=False).exists()
526 assert osp.isdir(smp) # module still exists
527 csmremoved = rwrepo.index.commit("Removed submodule")
528
529 # an update will remove the module
530 # not in dry_run
531 rm.update(recursive=False, dry_run=True, force_remove=True)
532 assert osp.isdir(smp)
533
534 # when removing submodules, we may get new commits as nested submodules are auto-committing changes
535 # to allow deletions without force, as the index would be dirty otherwise.
536 # QUESTION: Why does this seem to work in test_git_submodule_compatibility() ?
537 self.assertRaises(InvalidGitRepositoryError, rm.update, recursive=False, force_remove=False)
538 rm.update(recursive=False, force_remove=True)
539 assert not osp.isdir(smp)
540
541 # 'apply work' to the nested submodule and assure this is not removed/altered during updates
542 # Need to commit first, otherwise submodule.update wouldn't have a reason to change the head
543 touch(osp.join(nsm.module().working_tree_dir, 'new-file'))
544 # We cannot expect is_dirty to even run as we wouldn't reset a head to the same location
545 assert nsm.module().head.commit.hexsha == nsm.hexsha
546 nsm.module().index.add([nsm])
547 nsm.module().index.commit("added new file")
548 rm.update(recursive=False, dry_run=True, progress=prog) # would not change head, and thus doens't fail
549 # Everything we can do from now on will trigger the 'future' check, so no is_dirty() check will even run
550 # This would only run if our local branch is in the past and we have uncommitted changes
551
552 prev_commit = nsm.module().head.commit
553 rm.update(recursive=False, dry_run=False, progress=prog)
554 assert prev_commit == nsm.module().head.commit, "head shouldn't change, as it is in future of remote branch"
555
556 # this kills the new file
557 rm.update(recursive=True, progress=prog, force_reset=True)
558 assert prev_commit != nsm.module().head.commit, "head changed, as the remote url and its commit changed"
559
560 # change url ...
561 #===============
562 # ... to the first repository, this way we have a fast checkout, and a completely different
563 # repository at the different url
564 nsm.set_parent_commit(csmremoved)
565 nsmurl = Git.polish_url(osp.join(self.rorepo.working_tree_dir, rsmsp[0]))
566 with nsm.config_writer() as writer:
567 writer.set_value('url', nsmurl)
568 csmpathchange = rwrepo.index.commit("changed url")
569 nsm.set_parent_commit(csmpathchange)
570
571 # Now nsm head is in the future of the tracked remote branch
572 prev_commit = nsm.module().head.commit
573 # dry-run does nothing
574 rm.update(recursive=False, dry_run=True, progress=prog)
575 assert nsm.module().remotes.origin.url != nsmurl
576
577 rm.update(recursive=False, progress=prog, force_reset=True)
578 assert nsm.module().remotes.origin.url == nsmurl
579 assert prev_commit != nsm.module().head.commit, "Should now point to gitdb"
580 assert len(rwrepo.submodules) == 1
581 assert not rwrepo.submodules[0].children()[0].module_exists(), "nested submodule should not be checked out"
582
583 # add the submodule's changed commit to the index, which is what the
584 # user would do
585 # beforehand, update our instance's binsha with the new one
586 nsm.binsha = nsm.module().head.commit.binsha
587 rwrepo.index.add([nsm])
588
589 # change branch
590 #=================
591 # we only have one branch, so we switch to a virtual one, and back
592 # to the current one to trigger the difference
593 cur_branch = nsm.branch
594 nsmm = nsm.module()
595 prev_commit = nsmm.head.commit
596 for branch in ("some_virtual_branch", cur_branch.name):
597 with nsm.config_writer() as writer:
598 writer.set_value(Submodule.k_head_option, git.Head.to_full_path(branch))
599 csmbranchchange = rwrepo.index.commit("changed branch to %s" % branch)
600 nsm.set_parent_commit(csmbranchchange)
601 # END for each branch to change
602
603 # Lets remove our tracking branch to simulate some changes
604 nsmmh = nsmm.head
605 assert nsmmh.ref.tracking_branch() is None # never set it up until now
606 assert not nsmmh.is_detached
607
608 # dry run does nothing
609 rm.update(recursive=False, dry_run=True, progress=prog)
610 assert nsmmh.ref.tracking_branch() is None
611
612 # the real thing does
613 rm.update(recursive=False, progress=prog)
614
615 assert nsmmh.ref.tracking_branch() is not None
616 assert not nsmmh.is_detached
617
618 # recursive update
619 # =================
620 # finally we recursively update a module, just to run the code at least once
621 # remove the module so that it has more work
622 assert len(nsm.children()) >= 1 # could include smmap
623 assert nsm.exists() and nsm.module_exists() and len(nsm.children()) >= 1
624 # assure we pull locally only
625 nsmc = nsm.children()[0]
626 with nsmc.config_writer() as writer:
627 writer.set_value('url', subrepo_url)
628 rm.update(recursive=True, progress=prog, dry_run=True) # just to run the code
629 rm.update(recursive=True, progress=prog)
630
631 # gitdb: has either 1 or 2 submodules depending on the version
632 assert len(nsm.children()) >= 1 and nsmc.module_exists()
633
634 @with_rw_repo(k_no_subm_tag, bare=False)
635 def test_first_submodule(self, rwrepo):
636 assert len(list(rwrepo.iter_submodules())) == 0
637
638 for sm_name, sm_path in (('first', 'submodules/first'),
639 ('second', osp.join(rwrepo.working_tree_dir, 'submodules/second'))):
640 sm = rwrepo.create_submodule(sm_name, sm_path, rwrepo.git_dir, no_checkout=True)
641 assert sm.exists() and sm.module_exists()
642 rwrepo.index.commit("Added submodule " + sm_name)
643 # end for each submodule path to add
644
645 self.assertRaises(ValueError, rwrepo.create_submodule, 'fail', osp.expanduser('~'))
646 self.assertRaises(ValueError, rwrepo.create_submodule, 'fail-too',
647 rwrepo.working_tree_dir + osp.sep)
648
649 @with_rw_directory
650 def test_add_empty_repo(self, rwdir):
651 empty_repo_dir = osp.join(rwdir, 'empty-repo')
652
653 parent = git.Repo.init(osp.join(rwdir, 'parent'))
654 git.Repo.init(empty_repo_dir)
655
656 for checkout_mode in range(2):
657 name = 'empty' + str(checkout_mode)
658 self.assertRaises(ValueError, parent.create_submodule, name, name,
659 url=empty_repo_dir, no_checkout=checkout_mode and True or False)
660 # end for each checkout mode
661
662 @with_rw_directory
663 def test_list_only_valid_submodules(self, rwdir):
664 repo_path = osp.join(rwdir, 'parent')
665 repo = git.Repo.init(repo_path)
666 repo.git.submodule('add', self._small_repo_url(), 'module')
667 repo.index.commit("add submodule")
668
669 assert len(repo.submodules) == 1
670
671 # Delete the directory from submodule
672 submodule_path = osp.join(repo_path, 'module')
673 shutil.rmtree(submodule_path)
674 repo.git.add([submodule_path])
675 repo.index.commit("remove submodule")
676
677 repo = git.Repo(repo_path)
678 assert len(repo.submodules) == 0
679
680 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS,
681 """FIXME on cygwin: File "C:\\projects\\gitpython\\git\\cmd.py", line 671, in execute
682 raise GitCommandError(command, status, stderr_value, stdout_value)
683 GitCommandError: Cmd('git') failed due to: exit code(128)
684 cmdline: git add 1__Xava verbXXten 1_test _myfile 1_test_other_file 1_XXava-----verbXXten
685 stderr: 'fatal: pathspec '"1__çava verböten"' did not match any files'
686 FIXME on appveyor: see https://ci.appveyor.com/project/Byron/gitpython/build/1.0.185
687 """)
688 @with_rw_directory
689 def test_git_submodules_and_add_sm_with_new_commit(self, rwdir):
690 parent = git.Repo.init(osp.join(rwdir, 'parent'))
691 parent.git.submodule('add', self._small_repo_url(), 'module')
692 parent.index.commit("added submodule")
693
694 assert len(parent.submodules) == 1
695 sm = parent.submodules[0]
696
697 assert sm.exists() and sm.module_exists()
698
699 clone = git.Repo.clone_from(self._small_repo_url(),
700 osp.join(parent.working_tree_dir, 'existing-subrepository'))
701 sm2 = parent.create_submodule('nongit-file-submodule', clone.working_tree_dir)
702 assert len(parent.submodules) == 2
703
704 for _ in range(2):
705 for init in (False, True):
706 sm.update(init=init)
707 sm2.update(init=init)
708 # end for each init state
709 # end for each iteration
710
711 sm.move(sm.path + '_moved')
712 sm2.move(sm2.path + '_moved')
713
714 parent.index.commit("moved submodules")
715
716 with sm.config_writer() as writer:
717 writer.set_value('user.email', 'example@example.com')
718 writer.set_value('user.name', 'me')
719 smm = sm.module()
720 fp = osp.join(smm.working_tree_dir, 'empty-file')
721 with open(fp, 'w'):
722 pass
723 smm.git.add(Git.polish_url(fp))
724 smm.git.commit(m="new file added")
725
726 # submodules are retrieved from the current commit's tree, therefore we can't really get a new submodule
727 # object pointing to the new submodule commit
728 sm_too = parent.submodules['module_moved']
729 assert parent.head.commit.tree[sm.path].binsha == sm.binsha
730 assert sm_too.binsha == sm.binsha, "cached submodule should point to the same commit as updated one"
731
732 added_bies = parent.index.add([sm]) # addded base-index-entries
733 assert len(added_bies) == 1
734 parent.index.commit("add same submodule entry")
735 commit_sm = parent.head.commit.tree[sm.path]
736 assert commit_sm.binsha == added_bies[0].binsha
737 assert commit_sm.binsha == sm.binsha
738
739 sm_too.binsha = sm_too.module().head.commit.binsha
740 added_bies = parent.index.add([sm_too])
741 assert len(added_bies) == 1
742 parent.index.commit("add new submodule entry")
743 commit_sm = parent.head.commit.tree[sm.path]
744 assert commit_sm.binsha == added_bies[0].binsha
745 assert commit_sm.binsha == sm_too.binsha
746 assert sm_too.binsha != sm.binsha
747
748 # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, ## ACTUALLY skipped by `git.submodule.base#L869`.
749 # "FIXME: helper.wrapper fails with: PermissionError: [WinError 5] Access is denied: "
750 # "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\test_work_tree_unsupportedryfa60di\\master_repo\\.git\\objects\\pack\\pack-bc9e0787aef9f69e1591ef38ea0a6f566ec66fe3.idx") # noqa E501
751 @with_rw_directory
752 def test_git_submodule_compatibility(self, rwdir):
753 parent = git.Repo.init(osp.join(rwdir, 'parent'))
754 sm_path = join_path_native('submodules', 'intermediate', 'one')
755 sm = parent.create_submodule('mymodules/myname', sm_path, url=self._small_repo_url())
756 parent.index.commit("added submodule")
757
758 def assert_exists(sm, value=True):
759 assert sm.exists() == value
760 assert sm.module_exists() == value
761 # end
762
763 # As git is backwards compatible itself, it would still recognize what we do here ... unless we really
764 # muss it up. That's the only reason why the test is still here ... .
765 assert len(parent.git.submodule().splitlines()) == 1
766
767 module_repo_path = osp.join(sm.module().working_tree_dir, '.git')
768 assert module_repo_path.startswith(osp.join(parent.working_tree_dir, sm_path))
769 if not sm._need_gitfile_submodules(parent.git):
770 assert osp.isdir(module_repo_path)
771 assert not sm.module().has_separate_working_tree()
772 else:
773 assert osp.isfile(module_repo_path)
774 assert sm.module().has_separate_working_tree()
775 assert find_submodule_git_dir(module_repo_path) is not None, "module pointed to by .git file must be valid"
776 # end verify submodule 'style'
777
778 # test move
779 new_sm_path = join_path_native('submodules', 'one')
780 sm.move(new_sm_path)
781 assert_exists(sm)
782
783 # Add additional submodule level
784 csm = sm.module().create_submodule('nested-submodule', join_path_native('nested-submodule', 'working-tree'),
785 url=self._small_repo_url())
786 sm.module().index.commit("added nested submodule")
787 sm_head_commit = sm.module().commit()
788 assert_exists(csm)
789
790 # Fails because there are new commits, compared to the remote we cloned from
791 self.assertRaises(InvalidGitRepositoryError, sm.remove, dry_run=True)
792 assert_exists(sm)
793 assert sm.module().commit() == sm_head_commit
794 assert_exists(csm)
795
796 # rename nested submodule
797 # This name would move itself one level deeper - needs special handling internally
798 new_name = csm.name + '/mine'
799 assert csm.rename(new_name).name == new_name
800 assert_exists(csm)
801 assert csm.repo.is_dirty(index=True, working_tree=False), "index must contain changed .gitmodules file"
802 csm.repo.index.commit("renamed module")
803
804 # keep_going evaluation
805 rsm = parent.submodule_update()
806 assert_exists(sm)
807 assert_exists(csm)
808 with csm.config_writer().set_value('url', 'bar'):
809 pass
810 csm.repo.index.commit("Have to commit submodule change for algorithm to pick it up")
811 assert csm.url == 'bar'
812
813 self.assertRaises(Exception, rsm.update, recursive=True, to_latest_revision=True, progress=prog)
814 assert_exists(csm)
815 rsm.update(recursive=True, to_latest_revision=True, progress=prog, keep_going=True)
816
817 # remove
818 sm_module_path = sm.module().git_dir
819
820 for dry_run in (True, False):
821 sm.remove(dry_run=dry_run, force=True)
822 assert_exists(sm, value=dry_run)
823 assert osp.isdir(sm_module_path) == dry_run
824 # end for each dry-run mode
825
826 @with_rw_directory
827 def test_remove_norefs(self, rwdir):
828 parent = git.Repo.init(osp.join(rwdir, 'parent'))
829 sm_name = 'mymodules/myname'
830 sm = parent.create_submodule(sm_name, sm_name, url=self._small_repo_url())
831 assert sm.exists()
832
833 parent.index.commit("Added submodule")
834
835 assert sm.repo is parent # yoh was surprised since expected sm repo!!
836 # so created a new instance for submodule
837 smrepo = git.Repo(osp.join(rwdir, 'parent', sm.path))
838 # Adding a remote without fetching so would have no references
839 smrepo.create_remote('special', 'git@server-shouldnotmatter:repo.git')
840 # And we should be able to remove it just fine
841 sm.remove()
842 assert not sm.exists()
843
844 @with_rw_directory
845 def test_rename(self, rwdir):
846 parent = git.Repo.init(osp.join(rwdir, 'parent'))
847 sm_name = 'mymodules/myname'
848 sm = parent.create_submodule(sm_name, sm_name, url=self._small_repo_url())
849 parent.index.commit("Added submodule")
850
851 assert sm.rename(sm_name) is sm and sm.name == sm_name
852 assert not sm.repo.is_dirty(index=True, working_tree=False, untracked_files=False)
853
854 new_path = 'renamed/myname'
855 assert sm.move(new_path).name == new_path
856
857 new_sm_name = "shortname"
858 assert sm.rename(new_sm_name) is sm
859 assert sm.repo.is_dirty(index=True, working_tree=False, untracked_files=False)
860 assert sm.exists()
861
862 sm_mod = sm.module()
863 if osp.isfile(osp.join(sm_mod.working_tree_dir, '.git')) == sm._need_gitfile_submodules(parent.git):
864 assert sm_mod.git_dir.endswith(join_path_native('.git', 'modules', new_sm_name))
865 # end
866
867 @with_rw_directory
868 def test_branch_renames(self, rw_dir):
869 # Setup initial sandbox:
870 # parent repo has one submodule, which has all the latest changes
871 source_url = self._small_repo_url()
872 sm_source_repo = git.Repo.clone_from(source_url, osp.join(rw_dir, 'sm-source'), b='master')
873 parent_repo = git.Repo.init(osp.join(rw_dir, 'parent'))
874 sm = parent_repo.create_submodule('mysubmodule', 'subdir/submodule',
875 sm_source_repo.working_tree_dir, branch='master')
876 parent_repo.index.commit('added submodule')
877 assert sm.exists()
878
879 # Create feature branch with one new commit in submodule source
880 sm_fb = sm_source_repo.create_head('feature')
881 sm_fb.checkout()
882 new_file = touch(osp.join(sm_source_repo.working_tree_dir, 'new-file'))
883 sm_source_repo.index.add([new_file])
884 sm.repo.index.commit("added new file")
885
886 # change designated submodule checkout branch to the new upstream feature branch
887 with sm.config_writer() as smcw:
888 smcw.set_value('branch', sm_fb.name)
889 assert sm.repo.is_dirty(index=True, working_tree=False)
890 sm.repo.index.commit("changed submodule branch to '%s'" % sm_fb)
891
892 # verify submodule update with feature branch that leaves currently checked out branch in it's past
893 sm_mod = sm.module()
894 prev_commit = sm_mod.commit()
895 assert sm_mod.head.ref.name == 'master'
896 assert parent_repo.submodule_update()
897 assert sm_mod.head.ref.name == sm_fb.name
898 assert sm_mod.commit() == prev_commit, "Without to_latest_revision, we don't change the commit"
899
900 assert parent_repo.submodule_update(to_latest_revision=True)
901 assert sm_mod.head.ref.name == sm_fb.name
902 assert sm_mod.commit() == sm_fb.commit
903
904 # Create new branch which is in our past, and thus seemingly unrelated to the currently checked out one
905 # To make it even 'harder', we shall fork and create a new commit
906 sm_pfb = sm_source_repo.create_head('past-feature', commit='HEAD~20')
907 sm_pfb.checkout()
908 sm_source_repo.index.add([touch(osp.join(sm_source_repo.working_tree_dir, 'new-file'))])
909 sm_source_repo.index.commit("new file added, to past of '%r'" % sm_fb)
910
911 # Change designated submodule checkout branch to a new commit in its own past
912 with sm.config_writer() as smcw:
913 smcw.set_value('branch', sm_pfb.path)
914 sm.repo.index.commit("changed submodule branch to '%s'" % sm_pfb)
915
916 # Test submodule updates - must fail if submodule is dirty
917 touch(osp.join(sm_mod.working_tree_dir, 'unstaged file'))
918 # This doesn't fail as our own submodule binsha didn't change, and the reset is only triggered if
919 # to latest revision is True.
920 parent_repo.submodule_update(to_latest_revision=False)
921 sm_mod.head.ref.name == sm_pfb.name, "should have been switched to past head"
922 sm_mod.commit() == sm_fb.commit, "Head wasn't reset"
923
924 self.assertRaises(RepositoryDirtyError, parent_repo.submodule_update, to_latest_revision=True)
925 parent_repo.submodule_update(to_latest_revision=True, force_reset=True)
926 assert sm_mod.commit() == sm_pfb.commit, "Now head should have been reset"
927 assert sm_mod.head.ref.name == sm_pfb.name
928
929 @skipIf(not is_win, "Specifically for Windows.")
930 def test_to_relative_path_with_super_at_root_drive(self):
931 class Repo(object):
932 working_tree_dir = 'D:\\'
933 super_repo = Repo()
934 submodule_path = 'D:\\submodule_path'
935 relative_path = Submodule._to_relative_path(super_repo, submodule_path)
936 msg = '_to_relative_path should be "submodule_path" but was "%s"' % relative_path
937 assert relative_path == 'submodule_path', msg
938
939 @skipIf(True, 'for some unknown reason the assertion fails, even though it in fact is working in more common setup')
940 @with_rw_directory
941 def test_depth(self, rwdir):
942 parent = git.Repo.init(osp.join(rwdir, 'test_depth'))
943 sm_name = 'mymodules/myname'
944 sm_depth = 1
945 sm = parent.create_submodule(sm_name, sm_name, url=self._small_repo_url(), depth=sm_depth)
946 self.assertEqual(len(list(sm.module().iter_commits())), sm_depth)
+0
-108
git/test/test_tree.py less more
0 # test_tree.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5
6 from io import BytesIO
7 import sys
8 from unittest import skipIf
9
10 from git import (
11 Tree,
12 Blob
13 )
14 from git.test.lib import TestBase
15 from git.util import HIDE_WINDOWS_KNOWN_ERRORS
16
17 import os.path as osp
18
19
20 class TestTree(TestBase):
21
22 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and sys.version_info[:2] == (3, 5), """
23 File "C:\\projects\\gitpython\\git\\cmd.py", line 559, in execute
24 raise GitCommandNotFound(command, err)
25 git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
26 cmdline: git cat-file --batch-check""")
27 def test_serializable(self):
28 # tree at the given commit contains a submodule as well
29 roottree = self.rorepo.tree('6c1faef799095f3990e9970bc2cb10aa0221cf9c')
30 for item in roottree.traverse(ignore_self=False):
31 if item.type != Tree.type:
32 continue
33 # END skip non-trees
34 tree = item
35 # trees have no dict
36 self.assertRaises(AttributeError, setattr, tree, 'someattr', 1)
37
38 orig_data = tree.data_stream.read()
39 orig_cache = tree._cache
40
41 stream = BytesIO()
42 tree._serialize(stream)
43 assert stream.getvalue() == orig_data
44
45 stream.seek(0)
46 testtree = Tree(self.rorepo, Tree.NULL_BIN_SHA, 0, '')
47 testtree._deserialize(stream)
48 assert testtree._cache == orig_cache
49
50 # replaces cache, but we make sure of it
51 del(testtree._cache)
52 testtree._deserialize(stream)
53 # END for each item in tree
54
55 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and sys.version_info[:2] == (3, 5), """
56 File "C:\\projects\\gitpython\\git\\cmd.py", line 559, in execute
57 raise GitCommandNotFound(command, err)
58 git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
59 cmdline: git cat-file --batch-check""")
60 def test_traverse(self):
61 root = self.rorepo.tree('0.1.6')
62 num_recursive = 0
63 all_items = []
64 for obj in root.traverse():
65 if "/" in obj.path:
66 num_recursive += 1
67
68 assert isinstance(obj, (Blob, Tree))
69 all_items.append(obj)
70 # END for each object
71 assert all_items == root.list_traverse()
72
73 # limit recursion level to 0 - should be same as default iteration
74 assert all_items
75 assert 'CHANGES' in root
76 assert len(list(root)) == len(list(root.traverse(depth=1)))
77
78 # only choose trees
79 trees_only = lambda i, d: i.type == "tree"
80 trees = list(root.traverse(predicate=trees_only))
81 assert len(trees) == len([i for i in root.traverse() if trees_only(i, 0)])
82
83 # test prune
84 lib_folder = lambda t, d: t.path == "lib"
85 pruned_trees = list(root.traverse(predicate=trees_only, prune=lib_folder))
86 assert len(pruned_trees) < len(trees)
87
88 # trees and blobs
89 assert len(set(trees) | set(root.trees)) == len(trees)
90 assert len({b for b in root if isinstance(b, Blob)} | set(root.blobs)) == len(root.blobs)
91 subitem = trees[0][0]
92 assert "/" in subitem.path
93 assert subitem.name == osp.basename(subitem.path)
94
95 # assure that at some point the traversed paths have a slash in them
96 found_slash = False
97 for item in root.traverse():
98 assert osp.isabs(item.abspath)
99 if '/' in item.path:
100 found_slash = True
101 # END check for slash
102
103 # slashes in paths are supported as well
104 # NOTE: on py3, / doesn't work with strings anymore ...
105 assert root[item.path] == item == root / item.path
106 # END for each item
107 assert found_slash
+0
-286
git/test/test_util.py less more
0 # test_utils.py
1 # Copyright (C) 2008, 2009 Michael Trier (mtrier@gmail.com) and contributors
2 #
3 # This module is part of GitPython and is released under
4 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
5
6 import pickle
7 import tempfile
8 import time
9 from unittest import skipIf
10 from datetime import datetime
11
12 import ddt
13
14 from git.cmd import dashify
15 from git.compat import is_win
16 from git.objects.util import (
17 altz_to_utctz_str,
18 utctz_to_altz,
19 verify_utctz,
20 parse_date,
21 tzoffset,
22 from_timestamp)
23 from git.test.lib import TestBase
24 from git.util import (
25 LockFile,
26 BlockingLockFile,
27 get_user_id,
28 Actor,
29 IterableList,
30 cygpath,
31 decygpath
32 )
33
34
35 _norm_cygpath_pairs = (
36 (r'foo\bar', 'foo/bar'),
37 (r'foo/bar', 'foo/bar'),
38
39 (r'C:\Users', '/cygdrive/c/Users'),
40 (r'C:\d/e', '/cygdrive/c/d/e'),
41
42 ('C:\\', '/cygdrive/c/'),
43
44 (r'\\server\C$\Users', '//server/C$/Users'),
45 (r'\\server\C$', '//server/C$'),
46 ('\\\\server\\c$\\', '//server/c$/'),
47 (r'\\server\BAR/', '//server/BAR/'),
48
49 (r'D:/Apps', '/cygdrive/d/Apps'),
50 (r'D:/Apps\fOO', '/cygdrive/d/Apps/fOO'),
51 (r'D:\Apps/123', '/cygdrive/d/Apps/123'),
52 )
53
54 _unc_cygpath_pairs = (
55 (r'\\?\a:\com', '/cygdrive/a/com'),
56 (r'\\?\a:/com', '/cygdrive/a/com'),
57
58 (r'\\?\UNC\server\D$\Apps', '//server/D$/Apps'),
59 )
60
61
62 class TestIterableMember(object):
63
64 """A member of an iterable list"""
65 __slots__ = "name"
66
67 def __init__(self, name):
68 self.name = name
69
70 def __repr__(self):
71 return "TestIterableMember(%r)" % self.name
72
73
74 @ddt.ddt
75 class TestUtils(TestBase):
76
77 def setup(self):
78 self.testdict = {
79 "string": "42",
80 "int": 42,
81 "array": [42],
82 }
83
84 @skipIf(not is_win, "Paths specifically for Windows.")
85 @ddt.idata(_norm_cygpath_pairs + _unc_cygpath_pairs)
86 def test_cygpath_ok(self, case):
87 wpath, cpath = case
88 cwpath = cygpath(wpath)
89 self.assertEqual(cwpath, cpath, wpath)
90
91 @skipIf(not is_win, "Paths specifically for Windows.")
92 @ddt.data(
93 (r'./bar', 'bar'),
94 (r'.\bar', 'bar'),
95 (r'../bar', '../bar'),
96 (r'..\bar', '../bar'),
97 (r'../bar/.\foo/../chu', '../bar/chu'),
98 )
99 def test_cygpath_norm_ok(self, case):
100 wpath, cpath = case
101 cwpath = cygpath(wpath)
102 self.assertEqual(cwpath, cpath or wpath, wpath)
103
104 @skipIf(not is_win, "Paths specifically for Windows.")
105 @ddt.data(
106 r'C:',
107 r'C:Relative',
108 r'D:Apps\123',
109 r'D:Apps/123',
110 r'\\?\a:rel',
111 r'\\share\a:rel',
112 )
113 def test_cygpath_invalids(self, wpath):
114 cwpath = cygpath(wpath)
115 self.assertEqual(cwpath, wpath.replace('\\', '/'), wpath)
116
117 @skipIf(not is_win, "Paths specifically for Windows.")
118 @ddt.idata(_norm_cygpath_pairs)
119 def test_decygpath(self, case):
120 wpath, cpath = case
121 wcpath = decygpath(cpath)
122 self.assertEqual(wcpath, wpath.replace('/', '\\'), cpath)
123
124 def test_it_should_dashify(self):
125 self.assertEqual('this-is-my-argument', dashify('this_is_my_argument'))
126 self.assertEqual('foo', dashify('foo'))
127
128 def test_lock_file(self):
129 my_file = tempfile.mktemp()
130 lock_file = LockFile(my_file)
131 assert not lock_file._has_lock()
132 # release lock we don't have - fine
133 lock_file._release_lock()
134
135 # get lock
136 lock_file._obtain_lock_or_raise()
137 assert lock_file._has_lock()
138
139 # concurrent access
140 other_lock_file = LockFile(my_file)
141 assert not other_lock_file._has_lock()
142 self.assertRaises(IOError, other_lock_file._obtain_lock_or_raise)
143
144 lock_file._release_lock()
145 assert not lock_file._has_lock()
146
147 other_lock_file._obtain_lock_or_raise()
148 self.assertRaises(IOError, lock_file._obtain_lock_or_raise)
149
150 # auto-release on destruction
151 del(other_lock_file)
152 lock_file._obtain_lock_or_raise()
153 lock_file._release_lock()
154
155 def test_blocking_lock_file(self):
156 my_file = tempfile.mktemp()
157 lock_file = BlockingLockFile(my_file)
158 lock_file._obtain_lock()
159
160 # next one waits for the lock
161 start = time.time()
162 wait_time = 0.1
163 wait_lock = BlockingLockFile(my_file, 0.05, wait_time)
164 self.assertRaises(IOError, wait_lock._obtain_lock)
165 elapsed = time.time() - start
166 extra_time = 0.02
167 if is_win:
168 # for Appveyor
169 extra_time *= 6 # NOTE: Indeterministic failures here...
170 self.assertLess(elapsed, wait_time + extra_time)
171
172 def test_user_id(self):
173 self.assertIn('@', get_user_id())
174
175 def test_parse_date(self):
176 # test all supported formats
177 def assert_rval(rval, veri_time, offset=0):
178 self.assertEqual(len(rval), 2)
179 self.assertIsInstance(rval[0], int)
180 self.assertIsInstance(rval[1], int)
181 self.assertEqual(rval[0], veri_time)
182 self.assertEqual(rval[1], offset)
183
184 # now that we are here, test our conversion functions as well
185 utctz = altz_to_utctz_str(offset)
186 self.assertIsInstance(utctz, str)
187 self.assertEqual(utctz_to_altz(verify_utctz(utctz)), offset)
188 # END assert rval utility
189
190 rfc = ("Thu, 07 Apr 2005 22:13:11 +0000", 0)
191 iso = ("2005-04-07T22:13:11 -0200", 7200)
192 iso2 = ("2005-04-07 22:13:11 +0400", -14400)
193 iso3 = ("2005.04.07 22:13:11 -0000", 0)
194 alt = ("04/07/2005 22:13:11", 0)
195 alt2 = ("07.04.2005 22:13:11", 0)
196 veri_time_utc = 1112911991 # the time this represents, in time since epoch, UTC
197 for date, offset in (rfc, iso, iso2, iso3, alt, alt2):
198 assert_rval(parse_date(date), veri_time_utc, offset)
199 # END for each date type
200
201 # and failure
202 self.assertRaises(ValueError, parse_date, 'invalid format')
203 self.assertRaises(ValueError, parse_date, '123456789 -02000')
204 self.assertRaises(ValueError, parse_date, ' 123456789 -0200')
205
206 def test_actor(self):
207 for cr in (None, self.rorepo.config_reader()):
208 self.assertIsInstance(Actor.committer(cr), Actor)
209 self.assertIsInstance(Actor.author(cr), Actor)
210 # END assure config reader is handled
211
212 def test_actor_from_string(self):
213 self.assertEqual(Actor._from_string("name"), Actor("name", None))
214 self.assertEqual(Actor._from_string("name <>"), Actor("name", ""))
215 self.assertEqual(Actor._from_string("name last another <some-very-long-email@example.com>"),
216 Actor("name last another", "some-very-long-email@example.com"))
217
218 @ddt.data(('name', ''), ('name', 'prefix_'))
219 def test_iterable_list(self, case):
220 name, prefix = case
221 ilist = IterableList(name, prefix)
222
223 name1 = "one"
224 name2 = "two"
225 m1 = TestIterableMember(prefix + name1)
226 m2 = TestIterableMember(prefix + name2)
227
228 ilist.extend((m1, m2))
229
230 self.assertEqual(len(ilist), 2)
231
232 # contains works with name and identity
233 self.assertIn(name1, ilist)
234 self.assertIn(name2, ilist)
235 self.assertIn(m2, ilist)
236 self.assertIn(m2, ilist)
237 self.assertNotIn('invalid', ilist)
238
239 # with string index
240 self.assertIs(ilist[name1], m1)
241 self.assertIs(ilist[name2], m2)
242
243 # with int index
244 self.assertIs(ilist[0], m1)
245 self.assertIs(ilist[1], m2)
246
247 # with getattr
248 self.assertIs(ilist.one, m1)
249 self.assertIs(ilist.two, m2)
250
251 # test exceptions
252 self.assertRaises(AttributeError, getattr, ilist, 'something')
253 self.assertRaises(IndexError, ilist.__getitem__, 'something')
254
255 # delete by name and index
256 self.assertRaises(IndexError, ilist.__delitem__, 'something')
257 del(ilist[name2])
258 self.assertEqual(len(ilist), 1)
259 self.assertNotIn(name2, ilist)
260 self.assertIn(name1, ilist)
261 del(ilist[0])
262 self.assertNotIn(name1, ilist)
263 self.assertEqual(len(ilist), 0)
264
265 self.assertRaises(IndexError, ilist.__delitem__, 0)
266 self.assertRaises(IndexError, ilist.__delitem__, 'something')
267
268 def test_from_timestamp(self):
269 # Correct offset: UTC+2, should return datetime + tzoffset(+2)
270 altz = utctz_to_altz('+0200')
271 self.assertEqual(datetime.fromtimestamp(1522827734, tzoffset(altz)), from_timestamp(1522827734, altz))
272
273 # Wrong offset: UTC+58, should return datetime + tzoffset(UTC)
274 altz = utctz_to_altz('+5800')
275 self.assertEqual(datetime.fromtimestamp(1522827734, tzoffset(0)), from_timestamp(1522827734, altz))
276
277 # Wrong offset: UTC-9000, should return datetime + tzoffset(UTC)
278 altz = utctz_to_altz('-9000')
279 self.assertEqual(datetime.fromtimestamp(1522827734, tzoffset(0)), from_timestamp(1522827734, altz))
280
281 def test_pickle_tzoffset(self):
282 t1 = tzoffset(555)
283 t2 = pickle.loads(pickle.dumps(t1))
284 self.assertEqual(t1._offset, t2._offset)
285 self.assertEqual(t1._name, t2._name)
9393 func(path) # Will scream if still not possible to delete.
9494 except Exception as ex:
9595 if HIDE_WINDOWS_KNOWN_ERRORS:
96 raise SkipTest("FIXME: fails with: PermissionError\n {}".format(ex))
96 raise SkipTest("FIXME: fails with: PermissionError\n {}".format(ex)) from ex
9797 raise
9898
9999 return shutil.rmtree(path, False, onerror)
745745 fd = os.open(lock_file, flags, 0)
746746 os.close(fd)
747747 except OSError as e:
748 raise IOError(str(e))
748 raise IOError(str(e)) from e
749749
750750 self._owns_lock = True
751751
800800 while True:
801801 try:
802802 super(BlockingLockFile, self)._obtain_lock()
803 except IOError:
803 except IOError as e:
804804 # synity check: if the directory leading to the lockfile is not
805805 # readable anymore, raise an exception
806806 curtime = time.time()
807807 if not osp.isdir(osp.dirname(self._lock_file_path())):
808808 msg = "Directory containing the lockfile %r was not readable anymore after waiting %g seconds" % (
809809 self._lock_file_path(), curtime - starttime)
810 raise IOError(msg)
810 raise IOError(msg) from e
811811 # END handle missing directory
812812
813813 if curtime >= maxtime:
814814 msg = "Waited %g seconds for lock at %r" % (maxtime - starttime, self._lock_file_path())
815 raise IOError(msg)
815 raise IOError(msg) from e
816816 # END abort if we wait too long
817817 time.sleep(self._check_interval)
818818 else:
877877
878878 try:
879879 return getattr(self, index)
880 except AttributeError:
881 raise IndexError("No item found with id %r" % (self._prefix + index))
880 except AttributeError as e:
881 raise IndexError("No item found with id %r" % (self._prefix + index)) from e
882882 # END handle getattr
883883
884884 def __delitem__(self, index):
88
99 from distutils.command.build_py import build_py as _build_py
1010 from setuptools.command.sdist import sdist as _sdist
11 import fnmatch
1112 import os
1213 import sys
1314 from os import path
6566 print("WARNING: Couldn't find version line in file %s" % filename, file=sys.stderr)
6667
6768
69 def build_py_modules(basedir, excludes=[]):
70 # create list of py_modules from tree
71 res = set()
72 _prefix = os.path.basename(basedir)
73 for root, _, files in os.walk(basedir):
74 for f in files:
75 _f, _ext = os.path.splitext(f)
76 if _ext not in [".py"]:
77 continue
78 _f = os.path.join(root, _f)
79 _f = os.path.relpath(_f, basedir)
80 _f = "{}.{}".format(_prefix, _f.replace(os.sep, "."))
81 if any(fnmatch.fnmatch(_f, x) for x in excludes):
82 continue
83 res.add(_f)
84 return list(res)
85
86
6887 setup(
6988 name="GitPython",
7089 cmdclass={'build_py': build_py, 'sdist': sdist},
7392 author="Sebastian Thiel, Michael Trier",
7493 author_email="byronimo@gmail.com, mtrier@gmail.com",
7594 url="https://github.com/gitpython-developers/GitPython",
76 packages=find_packages('.'),
77 py_modules=['git.' + f[:-3] for f in os.listdir('./git') if f.endswith('.py')],
78 package_data={'git.test': ['fixtures/*']},
95 packages=find_packages(exclude=("test.*")),
96 include_package_data=True,
97 py_modules=build_py_modules("./git", excludes=["git.ext.*"]),
7998 package_dir={'git': 'git'},
8099 python_requires='>=3.4',
81100 install_requires=requirements,
11 coverage
22 flake8
33 tox
4 virtualenv