Klaus Demo ~jonashaag/klaus / 553cc5f
Experimental support for Python 3 Smart HTTP doesn't work yet (depends on jelmer/dulwich#295) Jonas Haag 6 years ago
8 changed file(s) with 51 addition(s) and 38 deletion(s). Raw diff Collapse all Expand all
00 import os
1 from six.moves import cStringIO
1 import io
2 import stat
23
34 import dulwich, dulwich.patch
45
5 from klaus.utils import check_output, force_unicode
6 from klaus.utils import check_output, force_unicode, parent_directory, encode_for_git, decode_from_git
67 from klaus.diff import prepare_udiff
78
89
1718
1819 def get_last_updated_at(self):
1920 refs = [self[ref_hash] for ref_hash in self.get_refs().values()]
20 refs.sort(key=lambda obj:getattr(obj, 'commit_time', None),
21 refs.sort(key=lambda obj:getattr(obj, 'commit_time', float('-inf')),
2122 reverse=True)
2223 if refs:
2324 return refs[0].commit_time
3031 """
3132 description = super(FancyRepo, self).get_description()
3233 if description:
34 description = force_unicode(description)
3335 if not description.startswith("Unnamed repository;"):
3436 return force_unicode(description)
3537
3638 def get_commit(self, rev):
37 rev = str(rev) # https://github.com/jelmer/dulwich/issues/144
3839 for prefix in ['refs/heads/', 'refs/tags/', '']:
3940 key = prefix + rev
4041 try:
41 obj = self[key]
42 obj = self[encode_for_git(key)]
4243 if isinstance(obj, dulwich.objects.Tag):
4344 obj = self[obj.object[1]]
4445 return obj
6263 return None
6364
6465 def get_sorted_ref_names(self, prefix, exclude=None):
65 refs = self.refs.as_dict(prefix)
66 refs = self.refs.as_dict(encode_for_git(prefix))
6667 if exclude:
6768 refs.pop(prefix + exclude, None)
6869
7273 return obj.tag_time
7374 return obj.commit_time
7475
75 return sorted(refs.keys(), key=get_commit_time, reverse=True)
76 return [decode_from_git(ref) for ref in
77 sorted(refs.keys(), key=get_commit_time, reverse=True)]
7678
7779 def get_branch_names(self, exclude=None):
7880 """ Returns a sorted list of branch names. """
107109 cmd.extend(['--', path])
108110
109111 sha1_sums = check_output(cmd, cwd=os.path.abspath(self.path))
110 return [self[sha1] for sha1 in sha1_sums.strip().split('\n')]
112 return [self[sha1] for sha1 in sha1_sums.strip().split(b'\n')]
111113
112114 def get_blob_or_tree(self, commit, path):
113115 """ Returns the Git tree or blob object for `path` at `commit`. """
118120 if isinstance(tree_or_blob, dulwich.objects.Blob):
119121 # Blobs don't have sub-files/folders.
120122 raise KeyError
121 tree_or_blob = self[tree_or_blob[part][1]]
123 tree_or_blob = self[tree_or_blob[encode_for_git(part)][1]]
122124 return tree_or_blob
123125
126 def listdir(self, commit, path):
127 dirs, files = [], []
128 for entry in self.get_blob_or_tree(commit, path).items():
129 name, entry = entry.path, entry.in_path(encode_for_git(path))
130 if entry.mode & stat.S_IFDIR:
131 dirs.append((name.lower(), name, entry.path))
132 else:
133 files.append((name.lower(), name, entry.path))
134 files.sort()
135 dirs.sort()
136
137 if path:
138 dirs.insert(0, (None, '..', parent_directory(path)))
139
140 return {'dirs' : dirs, 'files' : files}
141
124142 def commit_diff(self, commit):
125 from klaus.utils import guess_is_binary, force_unicode
143 from klaus.utils import guess_is_binary
126144
127145 if commit.parents:
128146 parent_tree = self[commit.parents[0]].tree
152170 # Dulwich will handle that.
153171 pass
154172
155 stringio = cStringIO.StringIO()
156 dulwich.patch.write_object_diff(stringio, self.object_store,
173 bytesio = io.BytesIO()
174 dulwich.patch.write_object_diff(bytesio, self.object_store,
157175 (oldpath, oldmode, oldsha),
158176 (newpath, newmode, newsha))
159 files = prepare_udiff(force_unicode(stringio.getvalue()),
160 want_header=False)
177 files = prepare_udiff(decode_from_git(bytesio.getvalue()), want_header=False)
161178 if not files:
162179 # the diff module doesn't handle deletions/additions
163180 # of empty files correctly.
22 import tarfile
33 from io import BytesIO
44 from contextlib import closing
5
6 from klaus.utils import encode_for_git, decode_from_git
57
68
79 class ListBytesIO(object):
7880 TreeEntry) along the way.
7981 """
8082 for entry in tree.iteritems():
81 entry_abspath = os.path.join(root, entry.path)
83 entry_abspath = os.path.join(root, decode_from_git(entry.path))
8284 if stat.S_ISDIR(entry.mode):
8385 for _ in walk_tree(repo, repo[entry.sha], entry_abspath):
8486 yield _
9595
9696
9797 def guess_is_binary(dulwich_blob):
98 return any('\0' in chunk for chunk in dulwich_blob.chunked)
98 return any(b'\0' in chunk for chunk in dulwich_blob.chunked)
9999
100100
101101 def guess_is_image(filename):
103103 if mime is None:
104104 return False
105105 return mime.startswith('image/')
106
107
108 def encode_for_git(s):
109 # XXX This assumes everything to be UTF-8 encoded
110 return s.encode('utf8')
111
112
113 def decode_from_git(b):
114 # XXX This assumes everything to be UTF-8 encoded
115 return b.decode('utf8')
106116
107117
108118 def force_unicode(s):
00 import os
1 import stat
21
32 from flask import request, render_template, current_app
43 from flask.views import View
98 from dulwich.objects import Blob
109
1110 from klaus import markup, tarutils
12 from klaus.utils import parent_directory, subpaths, pygmentize, \
11 from klaus.utils import parent_directory, subpaths, pygmentize, encode_for_git, \
1312 force_unicode, guess_is_binary, guess_is_image
1413
1514
10099 selected commit
101100 """
102101 root_directory = self.get_root_directory()
103 root_tree = self.context['repo'].get_blob_or_tree(
102 return self.context['repo'].listdir(
104103 self.context['commit'],
105104 root_directory
106105 )
107
108 dirs, files = [], []
109 for entry in root_tree.iteritems():
110 name, entry = entry.path, entry.in_path(root_directory)
111 if entry.mode & stat.S_IFDIR:
112 dirs.append((name.lower(), name, entry.path))
113 else:
114 files.append((name.lower(), name, entry.path))
115 files.sort()
116 dirs.sort()
117
118 if root_directory:
119 dirs.insert(0, (None, '..', parent_directory(root_directory)))
120
121 return {'dirs' : dirs, 'files' : files}
122106
123107 def get_root_directory(self):
124108 root_directory = self.context['path']
77 git commit -a -m "First commit"
88 )
99
10 py.test tests/
10 py.test tests/ -v
1414
1515 install_data_files_hack()
1616
17 requires = ['flask', 'pygments', 'dulwich>=0.9.6', 'httpauth', 'humanize']
17 requires = ['six', 'flask', 'pygments', 'dulwich>=0.9.6', 'httpauth', 'humanize']
1818
1919 try:
2020 import argparse # not available for Python 2.6
9393 tmp = tempfile.mkdtemp()
9494 try:
9595 return any([
96 "git clone" in http_get(TEST_REPO_URL).content,
96 b"git clone" in http_get(TEST_REPO_URL).content,
9797 _check_http200(http_get, TEST_REPO_URL + "info/refs?service=git-upload-pack"),
9898 subprocess.call(["git", "clone", url, tmp]) == 0,
9999 ])
1010 response_body = BytesIO(response.raw.read())
1111 tarball = tarfile.TarFile.gzopen("test.tar.gz", fileobj=response_body)
1212 with contextlib.closing(tarball):
13 assert tarball.extractfile('README').read() == 'Hello World\n'
13 assert tarball.extractfile('README').read() == b'Hello World\n'