gitar

Update file view code

Author
Maarten 'Vngngdn' Vangeneugden
Date
Oct. 19, 2017, 5:41 a.m.
Hash
84209d2e48ae8de4c56bda81754b2278f27ea70e
Parent
1ef9615a2e0f3db1a14effa0997c27cc1e3d0801
Modified files
templates/gitar/file.html
views.py

templates/gitar/file.html

5 additions and 7 deletions.

View changes Hide changes
1
1
2
2
{% block title %}Gitar | Index page{% endblock title %}
3
3
4
4
{% block stylesheets %}
5
5
<link href="/static/website/materialize/css/google-icons.css" rel="stylesheet" />
6
6
<link href="/static/website/materialize/css/materialize.css" rel="stylesheet" media="screen, projection" />
7
7
<link rel="stylesheet" href="https://cdn.rawgit.com/tonsky/FiraCode/1.204/distr/fira_code.css">
8
8
<!-- TODO: Download Fira Code stylesheet and serve via the static folder. -->
9
9
<!--<style>
10
10
td {
11
11
	padding: 0 0 0 0;
12
12
}
13
13
pre {
14
14
	margin-top: 10px;
15
15
	margin-bottom: 10px;
16
16
}
17
17
table {
18
18
	line-height: 0px;
19
19
	padding-top: 0px;
20
20
	padding-bottom: 0px;
21
21
	border-spacing: 0 0;
22
22
	margin-top: 0px;
23
23
	margin-bottom: 0px;
24
24
}
25
25
</style>-->
26
26
{# For the syntax coloring of Gitar. TODO for later. #}
27
27
<link rel="stylesheet" type="text/css" href="/static/website/syntax.css" />
28
28
<link rel="stylesheet" type="text/css" href="/static/gitar/css/file.css" />
29
29
{% endblock stylesheets %}
30
30
31
31
{% block description %}
+
32
{% block description %}
32
33
Vngngdn's Gitar app. Really nothing more to say, except that it FREAKING ROCKS!
33
-
{% endblock description %}
+
34
{% endblock description %}
34
35
{% block main %}
35
36
{% with mdac=materialDesign_accentColor %} {# You'll see why this is handy shortly. #}
36
37
<div class="section {{ materialDesign_color }} lighten-2">
37
38
	<p class="flow-text container white-text">
38
-
		Gitar is a simple web app to easily host Git repositories using the Django framework.
39
-
	</p>
40
-
</div>
41
39
<div class="container section">
42
-
43
-
	<table>
+
40
    <h3 class="{{mdac}}-text text-accent-3">{{title}}</h3>
+
41
	<table>
44
42
		{% for line in content %}
45
43
		<tr>
46
44
			<td id="{{ forloop.counter }}" class="line-number"><pre>{{ forloop.counter }}</pre></td>
47
-
			<td><pre>{{ line|safe }}</pre></td>
+
45
			<td><pre>{{ line|safe }}</pre></td>
48
46
		</tr>
49
47
		{% endfor %}
50
48
	</table>
51
49
{% endwith %}
52
50
{% endblock main %}
53
51

views.py

5 additions and 3 deletions.

View changes Hide changes
1
1
    Copyright © 2016 Maarten "Vngngdn" Vangeneugden
2
2
3
3
    This program is free software: you can redistribute it and/or modify
4
4
    it under the terms of the GNU Affero General Public License as
5
5
    published by the Free Software Foundation, either version 3 of the
6
6
    License, or (at your option) any later version.
7
7
8
8
    This program is distributed in the hope that it will be useful,
9
9
    but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
    GNU Affero General Public License for more details.
12
12
13
13
    You should have received a copy of the GNU Affero General Public License
14
14
    along with this program. If not, see https://www.gnu.org/licenses/agpl.html.
15
15
"""
16
16
17
17
from django.shortcuts import get_object_or_404, render  # This allows to render the template with the view here. It's pretty cool and important.
18
18
from django.http import HttpResponseRedirect, HttpResponse
19
19
from django.core.urlresolvers import reverse
20
20
from .models import *
21
21
22
22
from .GitActions import RepoInfo
23
23
24
24
from git import Repo  # GitPython functionality.
25
25
import git
26
26
27
27
from .syntax import *
28
28
29
29
# First, I list some standard variables that are common for most of the sites of this app.
30
30
31
31
def footer_description():
32
32
    return "Gitar is a simple web app that allows its users to easily share Git repos in combination with the Django framework."
33
33
34
34
def footer_links():
35
35
    footer_links = [
36
36
            #['Source', 'OHGODHELPNOTDONEYET'],
37
37
            ['Personal website', reverse('about-index')],
38
38
            ]
39
39
    return footer_links
40
40
41
41
def standard_context():
42
42
    context = {
43
43
            'materialDesign_color': "blue-grey",
44
44
            'materialDesign_accentColor': "green",
45
45
            'navbar_title': "Gitar",
46
46
            'navbar_backArrow': False,
47
47
            'footer_title': "Gitar",
48
48
            'footer_description': footer_description(),
49
49
            'footer_links': footer_links(),
50
50
            }
51
51
    return context
52
52
53
53
# From here, the actual views start.
54
54
def index(request):
55
55
    """ The start page of Gitar.
56
56
57
57
    The goal of this view, is to collect all the available repositories,
58
58
    including some additional information, such as programming language,
59
59
    license, description, ... in order to give a fast overview of the most
60
60
    prominent information.
61
61
    """
62
62
63
63
    # Collecting the available repositories:
64
64
    # Template:
65
65
    template = "gitar/index.html"
66
66
    # Requesting the repositories:
67
67
    modelRepos = Repository.objects.all()
68
68
    # From here, we start collecting info about all the repositories:
69
69
    class BlankRepository: pass  # Blank object in which all data will be collected.
70
70
    repositories = []
71
71
    for modelRepo in modelRepos:
72
72
        repository = BlankRepository()
73
73
        # TODO: Find a way to add all of modelRepo's fields without having to
74
74
        # hardcode them. This is prone to errors and is redundant.
75
75
        repository.name = str(modelRepo)
76
76
        repository.programmingLanguage = modelRepo.programmingLanguage
77
77
        repository.license = modelRepo.license
78
78
        repository.description = RepoInfo.get_description(modelRepo)
79
79
80
80
        #gitRepo = Repo.init(modelRepo.directory(), bare=True)  # Connects to the Git Repo.
81
81
        # See tests.py, which assures all repositories exist. Tests are handy.
82
82
        #repository.description = gitRepo.description
83
83
        # This is mostly personal taste, but I like to show the amount of files.
84
84
        #repoTree = gitRepo.heads.master.commit.tree
85
85
        #repository.fileCount = len(repoTree.blobs)  # blobs are files.
86
86
        repositories.append(repository)
87
87
    # After that, I extend the standard context with the repositories:
88
88
    context = standard_context()
89
89
    context['repositories'] = repositories
90
90
    # And finally, sending everything back.
91
91
    return render(request, template, context)
92
92
93
93
def commit(request, repository, commit):
94
94
    pass  # TODO
95
95
96
96
def repositories(request, repository_name, branch="master"):
97
97
    # A repo's root is a directory by default, so this will automatically return
98
98
    # a directory view. But still, this is a bit nicer.
99
99
    return path_explorer(request, repository_name, branch, "")
100
100
101
101
def path_explorer(request, repository_name, branch, path):
102
102
    """ Checks whether the given path is a file or a directory, and calls the
103
103
    appropriate view function accordingly.
104
104
    """
105
105
    repository = RepoInfo.get_repository_object(repository_name)
106
106
    # From the GitPython documentation:
107
107
    # You can obtain the tree object of a repository, which is the directory of
108
108
    # that repo. This tree can be accessed as if it were a native Python list,
109
109
    # where the elements are the subdirectories and files. So, the idea to
110
110
    # determine whether a file, or a directory was requested, is simple:
111
111
    # 1. Split the path with "/" as seperator.
112
112
    # 2. Replace the current tree variable with the one retrieved from the
113
113
    # subtree element
114
114
    # 3. Repeat 2. until all parts of the given path are exhausted.
115
115
    # If we now still have a tree, we're looking at a directory, so display the
116
116
    # files (and subdirectories) of this directory.
117
117
    # Else, if we hit a blob, display the file contents.
118
118
    path_parts = path.split(sep="/")
119
119
    # FIXME: This is a bug at the URL regex part that I haven't been able to fix
120
120
    # yet. This serves as a temporary fix:
121
121
    # If the last part of the path is an empty string (which happens when the
122
122
    # last symbol was a '/'), remove that part from the list.
123
123
    # Of course, this is bad monkeypatching, but I suck at regex, so as long as
124
124
    # I don't find the solution, this'll have to do.
125
125
126
126
127
127
    print(path_parts)
128
128
129
129
    if path_parts[len(path_parts)-1] == "":
130
130
        path_parts.pop()
131
131
132
132
    if len(path_parts) == 0:
133
133
        directory = repository.heads[branch].commit.tree
134
134
        return directory_view(request, repository_name, branch, path, directory)
135
135
136
136
    assert len(path_parts) != 0
137
137
138
138
    # FIXME: If the user gives a "<something>/../<somethingElse>", that should
139
139
    # become "<something>". Obviously, although I think that's done by default
140
140
    # already.
141
141
    directory = repository.heads[branch].commit.tree
142
142
    for i in range(len(path_parts)):
143
143
        subdirectories = directory.trees
144
144
        #if len(subdirectories) == 0:
145
145
            # This can't happen, as this would imply there is a directory inside
146
146
            # a file.
147
147
        #    assert False
148
148
        #else:
149
149
        for subdirectory in subdirectories:
150
150
            if subdirectory.name == path_parts[i]:
151
151
                directory = subdirectory
152
152
                #break  # Useless optimization
153
153
    # When there are no more directories to traverse, check if the last part of
154
154
    # the path is either a file, or a directory:
155
155
    blobs = directory.blobs
156
156
    print(path_parts)
157
157
    last_part = path_parts[len(path_parts)-1]
158
158
    for blob in directory.blobs:
159
159
        print(blob.name)
160
160
        if blob.name == last_part:
161
161
            file_blob = blob
162
162
            print("Returning file view")
163
163
            return file_view(request, repository_name, branch, path, file_blob)
164
164
        else:
165
165
            print("blob name: " + blob.name)
166
166
            print("last part: " + last_part)
167
167
    return directory_view(request, repository_name, branch, path, directory)
168
168
169
169
def directory_view(request, repository_name, branch, path, directory):
170
170
    """ Collects the given directories's files and subdirectories, and renders a
171
171
    template to display this data.
172
172
    """
173
173
174
174
    # Collecting files in this directory
175
175
    repository = RepoInfo.get_repository_object(repository_name)
176
176
    files = []
177
177
    for file in directory.blobs:
178
178
        files.append({
179
179
            "name":file.name,
180
180
            "path":file.path,
181
181
            "commit":"lol",#FileInfo.last_commit(repository, file).binsha,
182
182
            })
183
183
    # Collecting commits for this branch
184
184
    commits = []
185
185
    for commit in repository.iter_commits(branch):
186
186
        commits.append({
187
187
            "hash":commit.hexsha[:20],
188
188
            "author":commit.author,
189
189
            "description":commit.summary,
190
190
            })
191
191
    # Collecting subdirectories
192
192
    subdirectories = []
193
193
    for subdirectory in directory.trees:
194
194
        subdirectories.append({
195
195
            "path":subdirectory.path,
196
196
            "name":subdirectory.name,
197
197
            })
198
198
    # Collecting rendering information:
199
199
    template = "gitar/directory.html"
200
200
    context = standard_context()
201
201
    context["files"] = files
202
202
    context["subdirectories"] = subdirectories
203
203
    context["commits"] = commits
204
204
    context["branch"] = branch
205
205
    context["repository_name"] = repository_name
206
206
    context["repository_description"] = repository.description
207
207
    # Collection repo information
208
208
    for repo in Repository.objects.all():
209
209
        if str(repo) == repository_name:
210
210
            context["repository_language"] = repo.programmingLanguage
211
211
            context["repository_license"] = repo.license
212
212
            break
213
213
    branches = []
214
214
    for bbranch in repository.heads:
215
215
        branches.append(bbranch.name)
216
216
    context["branches"] = branches
217
217
    return render(request, template, context)
218
218
219
219
220
220
def file_view(request, repository_name, branch, path, ffile):
221
-
    """ Collects the file contents of the given file path, and returns it to the
+
221
    """ Collects the file contents of the given file path, and returns it to the
222
222
    template, with the file contents already formatted in HTML using Pygments.
223
223
    """
224
224
225
225
    # Turning the file's contents in HTML ready output:
226
226
    raw_file_data = ffile.data_stream.read()
227
-
    html_code = code_to_HTML(raw_file_data, ffile.name)
228
-
    # Collecting rendering information:
+
227
    html_code = code_to_HTML(raw_file_data, file.name)
+
228
    # Collecting rendering information:
229
229
    template = "gitar/file.html"
230
230
    context = standard_context()
231
231
    context["content"] = html_code
232
232
    return render(request, template, context)
+
233
    context["repository_name"] = repository_name
+
234
    return render(request, template, context)
233
235
    
234
236