gitar

Prepare Gitar for internationalization

Author
Maarten 'Vngngdn' Vangeneugden
Date
Oct. 19, 2017, 6:21 p.m.
Hash
140301439f9da032a0f874bb5ee3a31ce9ce73fe
Parent
ecb197b6acbe073d40cb56f2c84cee1aa7b250cc
Modified files
templates/gitar/directory.html
templates/gitar/index.html
views.py

templates/gitar/directory.html

3 additions and 3 deletions.

View changes Hide changes
1
1
{% load i18n %}
2
2
{% block title %}{{ repository_name }} | Gitar{% endblock title %}
3
3
{% block description %}
4
4
{{repository_description}}
5
5
{% endblock description %}
6
6
{% block main %}
7
7
{% with mdac=materialDesign_accentColor mdc=materialDesign_color %} {# You'll see why this is handy shortly. #}
8
8
<div class="section {{ materialDesign_color }} lighten-2">
9
9
</div>
10
10
<div class="section">
11
11
    <div class="row">
12
12
        <div class="col hide-on-med-and-down l4">
13
13
            <!-- Add tertiary information such as branches and licensing here.  -->
14
14
            <h3 class="{{mdc}}-text">{{repository_name}}</h3>
15
15
            <h5 class="{{mdc}}-text">{% trans "Description" %}</h5>
16
16
            {{repository_description}}
17
17
            <h5 class="{{mdc}}-text">Branches</h5>
18
-
            {% for bbranch in branches %}
+
18
            {% for bbranch in branches %}
19
19
            <a class="{{mdac}}-text text-accent-3" href="{% url 'gitar-repository' repository_name bbranch %}">
20
20
                {{bbranch}}
21
21
            </a><br />
22
22
            {% endfor %}
23
23
            <h5 class="{{mdc}}-text">{% trans "Extra information" %}</h5>
24
24
            <div class="chip">
25
25
                {{repository_language}}
26
26
                <i class="material-icons {{mdac}}-text text-accent-3">code</i>
27
27
            </div><br />
28
28
            <div class="chip">
29
29
                {{repository_license}}
30
30
                <i class="material-icons {{mdac}}-text text-accent-3">copyright</i>
31
31
            </div><br />
32
32
        </div>
33
33
        <div class="col s12 m8 l5">
34
34
            <!-- Main area with links to files and subdirectories -->
35
35
            <h3 class="{{mdc}}-text">Files</h3>
36
-
            <table class="highlight">
+
36
            <table class="highlight">
37
37
                {% if subdirectories %}
38
38
                <thead>
39
39
                    {% for subdirectory in subdirectories %}
40
40
                    <tr>
41
41
                        <th>
42
42
                        <a class="{{mdac}}-text text-accent-4" href="{% url 'gitar-path-explorer' repository_name branch subdirectory.path %}">
43
43
                            {{subdirectory.name}}
44
44
                        </a>
45
45
                        </th>
46
46
                    </tr>
47
47
                    {% endfor %}
48
48
                </thead>
49
49
                {% endif %}
50
50
                <tbody>
51
51
                    {% for file in files %}
52
52
                    <tr>
53
53
                        <td>
54
54
                        <a class="{{mdac}}-text text-accent-3" href="{% url 'gitar-path-explorer' repository_name branch file.path %}">
55
55
                            {{file.name}}
56
56
                        </a>
57
57
                        </td>
58
58
                            <td>{{file.commit|truncatechars:6}}</td>
59
59
                    </tr>
60
60
                    {% endfor %}
61
61
                </tbody>
62
62
            </table>
63
63
        </div>
64
64
        <div class="col hide-on-small-only m4 l3">
65
65
            <!-- List of commits on the current branch, chronologically. -->
66
66
            <h3 class="{{mdc}}-text">Commits</h3>
67
-
            {% for commit in commits %}
+
67
            {% for commit in commits %}
68
68
            <hr />
69
69
            <a
70
70
                class="{{mdac}}-text text-accent-3 tooltipped"
71
71
                {# href="{% url 'gitar-commit' repository_name commit.hash %}" #}
72
72
                data-position="left"
73
73
                data-delay="50"
74
74
                data-tooltip="Viewing commits is not implemented yet!">
75
75
                {{commit.hash|truncatechars:15}}
76
76
            </a>
77
77
            <span class="{{mdc}}-text text-lighten-2">
78
78
                {% trans "by" %} {{commit.author}}
79
79
            </span><br />
80
80
            {{commit.description|lower|capfirst}}{% if commit.description|last != "." %}.{% endif %}
81
81
            {% endfor %}
82
82
        </div>
83
83
    </div>
84
84
</div>
85
85
{% endwith %}
86
86
{% endblock main %}
87
87

templates/gitar/index.html

12 additions and 9 deletions.

View changes Hide changes
1
1
{% load i18n %}
2
2
3
3
{% block title %}Gitar | Index page{% endblock title %}
4
-
{% block description %}
+
4
{% block description %}
5
5
Maarten's Gitar app. Still under heavy development, but maintained with &lt;3
6
-
{% endblock description %}
+
6
{% endblock description %}
7
7
{% block main %}
8
8
{% with mdac=materialDesign_accentColor %} {# You'll see why this is handy shortly. #}
9
9
{% with mdc=materialDesign_color %}
10
10
<div class="section {{ materialDesign_color }} lighten-2">
11
11
	<p class="flow-text container white-text">
12
12
		Gitar is a simple web app to easily host Git repositories using the Django framework.
13
-
	</p>
+
13
	</p>
14
14
</div>
15
15
<div class="container section">
16
16
    <h3 class="{{ materialDesign_color }}-text">About Gitar</h3>
17
-
    <p>
+
17
    <p>
18
18
        {% blocktrans %}Gitar is a hobby project of me, to make it easy for
19
19
        people to scroll through the code I publish, in a read-only fashion. It
20
20
        makes use of
21
21
        <a class="{{ mdac }}-text text-accent-3" href="http://pygments.org/">Pygments</a>
22
22
        to read the source files, and apply the appropriate syntax coloring.
23
23
        {% endblocktrans %}
24
24
    </p>
25
25
    <p>
26
26
        {% blocktrans %}Gitar <b>is NOT stable, and under heavy development!</b>
27
-
        It's currently able to display code, and traverse a source tree, but is
28
-
        limited to the master branch, and does not feature extras like a mailing
29
-
        list.<br />
30
-
        Also, if you happen to walk in while I'm working, it's possible you'll
+
27
        have been pushed to the server, without any manual intervention from me.
+
28
        Special attention goes to clean URL design, adhering to web standards,
+
29
        and responsive design across all screen types.{% endblocktrans %}
+
30
    <p>
+
31
        {% blocktrans %}Gitar <b>is a project under development!</b>
+
32
        While it's certainly presentable, there's still a lot of room for improvement.<br />
+
33
        Also, if you happen to walk in while I'm working, it's possible you'll
31
34
        fall through the floor, so be warned =D{% endblocktrans %}
32
35
    </p>
33
36
</div>
34
37
<div class="container section">
35
38
    <h3 class="{{ materialDesign_color }}-text">Public repositories</h3>
36
-
		{% for repository in repositories %} {# ARGH DON'T YOU LOVE THE READABILITY #}
+
39
		{% for repository in repositories %} {# ARGH DON'T YOU LOVE THE READABILITY #}
37
40
        <div class="row">
38
41
            <div class="col m3 valign-wrapper">
39
42
                <a class="valign waves-effect btn white {{ mdac }} accent-3" href="{% url 'gitar-repository' repository_name=repository.name %}">
40
43
                    {{ repository.name }}
41
44
                </a>
42
45
            </div>
43
46
            <div class="col m7">
44
47
                <p> {{ repository.description }} </p>
45
48
            </div>
46
49
            <div class="col m2">
47
50
            <ul>
48
51
                <li><i class="material-icons {{ mdac }}-text text-accent-3">code</i>
49
52
                    {{ repository.programmingLanguage }}</li>
50
53
                <!--<li><i class="material-icons">description</i> 
51
54
                    {{ repository.fileCount }}</li>-->
52
55
                <li><i class="material-icons {{ mdc }}-text">copyright</i>
53
56
                    {{ repository.license }}</li>
54
57
            </ul>
55
58
            </div>
56
59
        </div>
57
60
		{% endfor %}
58
61
	</div>
59
62
{% endwith %}
60
63
{% endwith %}
61
64
{% endblock main %}
62
65

views.py

3 additions and 2 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
            [_('Source code'), reverse('gitar-repository', 'gitar')],
+
39
            ]
39
40
    return footer_links
40
41
41
42
def standard_context():
42
43
    context = {
43
44
            'materialDesign_color': "blue-grey",
44
45
            'materialDesign_accentColor': "green",
45
46
            'navbar_title': "Gitar",
46
47
            'navbar_backArrow': False,
47
48
            'footer_title': "Gitar",
48
49
            'footer_description': footer_description(),
49
50
            'footer_links': footer_links(),
50
51
            }
51
52
    return context
52
53
53
54
# From here, the actual views start.
54
55
def index(request):
55
56
    """ The start page of Gitar.
56
57
57
58
    The goal of this view, is to collect all the available repositories,
58
59
    including some additional information, such as programming language,
59
60
    license, description, ... in order to give a fast overview of the most
60
61
    prominent information.
61
62
    """
62
63
63
64
    # Collecting the available repositories:
64
65
    # Template:
65
66
    template = "gitar/index.html"
66
67
    # Requesting the repositories:
67
68
    modelRepos = Repository.objects.all()
68
69
    # From here, we start collecting info about all the repositories:
69
70
    class BlankRepository: pass  # Blank object in which all data will be collected.
70
71
    repositories = []
71
72
    for modelRepo in modelRepos:
72
73
        repository = BlankRepository()
73
74
        # TODO: Find a way to add all of modelRepo's fields without having to
74
75
        # hardcode them. This is prone to errors and is redundant.
75
76
        repository.name = str(modelRepo)
76
77
        repository.programmingLanguage = modelRepo.programmingLanguage
77
78
        repository.license = modelRepo.license
78
79
        repository.description = RepoInfo.get_description(modelRepo)
79
80
80
81
        #gitRepo = Repo.init(modelRepo.directory(), bare=True)  # Connects to the Git Repo.
81
82
        # See tests.py, which assures all repositories exist. Tests are handy.
82
83
        #repository.description = gitRepo.description
83
84
        # This is mostly personal taste, but I like to show the amount of files.
84
85
        #repoTree = gitRepo.heads.master.commit.tree
85
86
        #repository.fileCount = len(repoTree.blobs)  # blobs are files.
86
87
        repositories.append(repository)
87
88
    # After that, I extend the standard context with the repositories:
88
89
    context = standard_context()
89
90
    context['repositories'] = repositories
90
91
    # And finally, sending everything back.
91
92
    return render(request, template, context)
92
93
93
94
def commit(request, repository, commit):
94
95
    pass  # TODO
95
96
96
97
def repositories(request, repository_name, branch="master"):
97
98
    # A repo's root is a directory by default, so this will automatically return
98
99
    # a directory view. But still, this is a bit nicer.
99
100
    return path_explorer(request, repository_name, branch, "")
100
101
101
102
def path_explorer(request, repository_name, branch, path):
102
103
    """ Checks whether the given path is a file or a directory, and calls the
103
104
    appropriate view function accordingly.
104
105
    """
105
106
    repository = RepoInfo.get_repository_object(repository_name)
106
107
    # From the GitPython documentation:
107
108
    # You can obtain the tree object of a repository, which is the directory of
108
109
    # that repo. This tree can be accessed as if it were a native Python list,
109
110
    # where the elements are the subdirectories and files. So, the idea to
110
111
    # determine whether a file, or a directory was requested, is simple:
111
112
    # 1. Split the path with "/" as seperator.
112
113
    # 2. Replace the current tree variable with the one retrieved from the
113
114
    # subtree element
114
115
    # 3. Repeat 2. until all parts of the given path are exhausted.
115
116
    # If we now still have a tree, we're looking at a directory, so display the
116
117
    # files (and subdirectories) of this directory.
117
118
    # Else, if we hit a blob, display the file contents.
118
119
    path_parts = path.split(sep="/")
119
120
    # FIXME: This is a bug at the URL regex part that I haven't been able to fix
120
121
    # yet. This serves as a temporary fix:
121
122
    # If the last part of the path is an empty string (which happens when the
122
123
    # last symbol was a '/'), remove that part from the list.
123
124
    # Of course, this is bad monkeypatching, but I suck at regex, so as long as
124
125
    # I don't find the solution, this'll have to do.
125
126
126
127
127
128
    print(path_parts)
128
129
129
130
    if path_parts[len(path_parts)-1] == "":
130
131
        path_parts.pop()
131
132
132
133
    if len(path_parts) == 0:
133
134
        directory = repository.heads[branch].commit.tree
134
135
        return directory_view(request, repository_name, branch, path, directory)
135
136
136
137
    assert len(path_parts) != 0
137
138
138
139
    # FIXME: If the user gives a "<something>/../<somethingElse>", that should
139
140
    # become "<something>". Obviously, although I think that's done by default
140
141
    # already.
141
142
    directory = repository.heads[branch].commit.tree
142
143
    for i in range(len(path_parts)):
143
144
        subdirectories = directory.trees
144
145
        #if len(subdirectories) == 0:
145
146
            # This can't happen, as this would imply there is a directory inside
146
147
            # a file.
147
148
        #    assert False
148
149
        #else:
149
150
        for subdirectory in subdirectories:
150
151
            if subdirectory.name == path_parts[i]:
151
152
                directory = subdirectory
152
153
                #break  # Useless optimization
153
154
    # When there are no more directories to traverse, check if the last part of
154
155
    # the path is either a file, or a directory:
155
156
    blobs = directory.blobs
156
157
    print(path_parts)
157
158
    last_part = path_parts[len(path_parts)-1]
158
159
    for blob in directory.blobs:
159
160
        print(blob.name)
160
161
        if blob.name == last_part:
161
162
            file_blob = blob
162
163
            print("Returning file view")
163
164
            return file_view(request, repository_name, branch, path, file_blob)
164
165
        else:
165
166
            print("blob name: " + blob.name)
166
167
            print("last part: " + last_part)
167
168
    return directory_view(request, repository_name, branch, path, directory)
168
169
169
170
def directory_view(request, repository_name, branch, path, directory):
170
171
    """ Collects the given directories's files and subdirectories, and renders a
171
172
    template to display this data.
172
173
    """
173
174
174
175
    # Collecting files in this directory
175
176
    repository = RepoInfo.get_repository_object(repository_name)
176
177
    files = []
177
178
    for file in directory.blobs:
178
179
        files.append({
179
180
            "name":file.name,
180
181
            "path":file.path,
181
182
            "commit":"",#FileInfo.last_commit(repository, file).hexsha[:20],
182
183
            })
183
184
    # Collecting commits for this branch
184
185
    commits = []
185
186
    for commit in repository.iter_commits(branch):
186
187
        commits.append({
187
188
            "hash":commit.hexsha[:20],
188
189
            "author":commit.author,
189
190
            "description":commit.summary,
190
191
            })
191
192
    # Collecting subdirectories
192
193
    subdirectories = []
193
194
    for subdirectory in directory.trees:
194
195
        subdirectories.append({
195
196
            "path":subdirectory.path,
196
197
            "name":subdirectory.name,
197
198
            })
198
199
    # Collecting rendering information:
199
200
    template = "gitar/directory.html"
200
201
    context = standard_context()
201
202
    context["files"] = files
202
203
    context["subdirectories"] = subdirectories
203
204
    context["commits"] = commits
204
205
    context["branch"] = branch
205
206
    context["repository_name"] = repository_name
206
207
    context["repository_description"] = repository.description
207
208
    # Collection repo information
208
209
    for repo in Repository.objects.all():
209
210
        if str(repo) == repository_name:
210
211
            context["repository_language"] = repo.programmingLanguage
211
212
            context["repository_license"] = repo.license
212
213
            break
213
214
    branches = []
214
215
    for bbranch in repository.heads:
215
216
        branches.append(bbranch.name)
216
217
    context["branches"] = branches
217
218
    return render(request, template, context)
218
219
219
220
220
221
def file_view(request, repository_name, branch, path, file):
221
222
    """ Collects the file contents of the given file path, and returns it to the
222
223
    template, with the file contents already formatted in HTML using Pygments.
223
224
    """
224
225
225
226
    # Turning the file's contents in HTML ready output:
226
227
    raw_file_data = file.data_stream.read()
227
228
    html_code = code_to_HTML(raw_file_data, file.name)
228
229
    # Collecting rendering information:
229
230
    template = "gitar/file.html"
230
231
    context = standard_context()
231
232
    context["content"] = html_code
232
233
    context["file_name"] = file.name
233
234
    context["repository_name"] = repository_name
234
235
    return render(request, template, context)
235
236
    
236
237