gitar

Added Pygments as a class C dependency, and finished the directory view function in views.py.

Author
Vngngdn
Date
Sept. 8, 2016, 9:03 p.m.
Hash
289e3c93312b178e3a408ca09ae1295d823a1499
Parent
165943b00b2d6fcfb2f44c9675a33b492f0e7ea7
Modified files
DEPENDENCIES.md
views.py

DEPENDENCIES.md

2 additions and 0 deletions.

View changes Hide changes
1
1
============
2
2
3
3
Since web apps (and everything web related) are known to suck at dependency handling (which is why we have Bower, NPM, cdnjs, docker, ... (I'll explain sometime somewhere why this is done, and why I don't like it), I've decided to take matters in my own hands; I'll just provide one simple markdown file listing all dependencies in human-readable format. I don't care whether this helps or not, but no harm is done, right?
4
4
5
5
Legend
6
6
------
7
7
8
8
The dependencies themselves have been ranked with a certain grade. I explain what they mean here:
9
9
10
10
 * A : This dependency is present inside the app. This will be in the form of ready-to-use source code files. As such, they need no further attention.
11
11
 * B : This dependency is present inside the app. This will be in the form of an archive file (i.e. .tar.gz), OR this needs additional work to function properly. In these cases, I refer to their documentation which will be available at the location of the files.
12
12
 * C : This dependency does not come with the app. These are often system packages, which often means (if you're on GNU/Linux) you'll have to search for it in your repositories. Their documentation is your last resort for these if it doesn't work as it should.
13
13
 
14
14
I hope I never will, but when it's necessary, I'll add a D grade, for unreadable, egregious bogus software that will give you all horrible kinds of diseases if you dare to work with it, but are indispensable to make the web app function. Just be happy I don't use it yet. (For example, PHP qualifies as D, so praise [our lord and saviour](https://rms.sexy) I write Python.)
15
15
16
16
A
17
17
-
18
18
19
19
B
20
20
-
21
21
22
22
C
23
23
-
24
24
 * [GitPython](https://github.com/gitpython-developers/GitPython): Provides a
25
25
   wrapper to ease Git interaction from Python.
26
26
 * [PostgreSQL](https://postgresql.org): PostgreSQL is (currently) the only
27
27
   supported database.
28
28
+
29
   code.
+
30

views.py

17 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
# First, I list some standard variables that are common for most of the sites of this app.
28
28
29
29
def footer_description():
30
30
    return "Gitar is a simple web app that allows its users to easily share Git repos in combination with the Django framework."
31
31
32
32
def footer_links():
33
33
    footer_links = [
34
34
            ['Source', 'OHGODHELPNOTDONEYET'],
35
35
            ['Personal website', reverse('about-index')],
36
36
            ]
37
37
    return footer_links
38
38
39
39
def standard_context():
40
40
    context = {
41
41
            'materialDesign_color': "blue-grey",
42
42
            'materialDesign_accentColor': "green",
43
43
            'navbar_title': "Gitar",
44
44
            'navbar_backArrow': False,
45
45
            'footer_title': "Gitar",
46
46
            'footer_description': footer_description(),
47
47
            'footer_links': footer_links(),
48
48
            }
49
49
    return context
50
50
51
51
# From here, the actual views start.
52
52
def index(request):
53
53
    """ The start page of Gitar.
54
54
55
55
    The goal of this view, is to collect all the available repositories,
56
56
    including some additional information, such as programming language,
57
57
    license, description, ... in order to give a fast overview of the most
58
58
    prominent information.
59
59
    """
60
60
61
61
    # Collecting the available repositories:
62
62
    # Template:
63
63
    template = "gitar/index.html"
64
64
    # Requesting the repositories:
65
65
    modelRepos = Repository.objects.all()
66
66
    # From here, we start collecting info about all the repositories:
67
67
    class BlankRepository: pass  # Blank object in which all data will be collected.
68
68
    repositories = []
69
69
    for modelRepo in modelRepos:
70
70
        repository = BlankRepository()
71
71
        # TODO: Find a way to add all of modelRepo's fields without having to
72
72
        # hardcode them. This is prone to errors and is redundant.
73
73
        repository.name = str(modelRepo)
74
74
        repository.programmingLanguage = modelRepo.programmingLanguage
75
75
        repository.license = modelRepo.license
76
76
        repository.description = RepoInfo.get_description(modelRepo)
77
77
78
78
        #gitRepo = Repo.init(modelRepo.directory(), bare=True)  # Connects to the Git Repo.
79
79
        # See tests.py, which assures all repositories exist. Tests are handy.
80
80
        #repository.description = gitRepo.description
81
81
        # This is mostly personal taste, but I like to show the amount of files.
82
82
        #repoTree = gitRepo.heads.master.commit.tree
83
83
        #repository.fileCount = len(repoTree.blobs)  # blobs are files.
84
84
        repositories.append(repository)
85
85
    # After that, I extend the standard context with the repositories:
86
86
    context = standard_context()
87
87
    context['repositories'] = repositories
88
88
    # And finally, sending everything back.
89
89
    return render(request, template, context)
90
90
91
91
def repositories(request, repositoryName):
92
92
    # I first form the repository link out the given name.
93
93
    # TODO: Form repo link out of given name.
94
-
    print(repositoryName)
95
-
    repository = RepoInfo.get_repository_object(repositoryName)
96
94
    assert repository.bare  # My own repos are always bare.
97
95
    content = repository.heads.master.commit.tree
98
96
99
97
    # Out of which I can deduce the files:
100
98
    files = content.blobs
101
99
    fileNames = []
102
100
    for filee in files:
103
101
        fileNames.append(filee.name)
104
102
    template = "gitar/repositories.html"
105
103
    context = standard_context()
106
104
    context['files'] = fileNames
107
105
108
106
    assert len(content.blobs) > 0
109
107
    assert len(fileNames) > 0
110
108
    return render(request, template, context)
111
109
112
110
def path_explorer(request, repository_name, path):
113
111
    """ Checks whether the given path is a file or a directory, and calls the
114
112
    appropriate view function accordingly.
115
113
    """
116
114
    repository = RepoInfo.get_repository_object(repository_name)
117
115
    # From the GitPython documentation:
118
116
    # You can obtain the tree object of a repository, which is the directory of
119
117
    # that repo. This tree can be accessed as if it were a native Python list,
120
118
    # where the elements are the subdirectories and files. So, the idea to
121
119
    # determine whether a file, or a directory was requested, is simple:
122
120
    # 1. Split the path with "/" as seperator.
123
121
    # 2. Replace the current tree variable with the one retrieved from the
124
122
    # subtree element
125
123
    # 3. Repeat 2. until all parts of the given path are exhausted.
126
124
    # If we now still have a tree, we're looking at a directory, so display the
127
125
    # files (and subdirectories) of this directory.
128
126
    # Else, if we hit a blob, display the file contents.
129
127
    path_parts = path.split(sep="/")
130
128
    # FIXME: If the user gives a "<something>/../<somethingElse>", that should
131
129
    # become "<something>". Obviously, although I think that's done by default
132
130
    # already.
133
131
    directory = repository.heads.master.commit.tree
134
132
    for i in range(len(path_parts)):
135
133
        subdirectories = directory.trees
136
134
        if len(subdirectories) == 0:
137
135
            # If there's no more subdirectory, and we get here, then that means
138
136
            # it's a file for sure, because otherwise, the iterator would've
139
137
            # stopped.
140
138
            file_blob = directory.blobs[path_parts[i]]
141
139
            return file_viewer(request, repository_name, file_blob)
142
140
        else:
143
141
            directory = subdirectories[path_parts[i]]
144
142
    # Current state:
145
143
    # The entire path was traversed, and we kept reaching subdirectories, which
146
144
    # means that the current directory was requested, and not a file. Thus,
147
145
    # display the directory.
148
146
    return directory_view(request, repository_name, directory)
149
147
150
148
def directory_view(request, repository_name, path, directory):
151
149
    """ Collects the given directories's files and subdirectories, and renders a
152
150
    template to display this data.
153
151
    """
154
152
+
153
    files = directory.blobs
+
154
    file_names = []
+
155
    for ffile in files:
+
156
        file_names.append(ffile.name)
+
157
    # Collecting all subdirectories:
+
158
    subdirectories = directory.trees
+
159
    subdirectory_names = []
+
160
    for subdirectory in subdirectories:
+
161
        subdirectory_names.append(subdirectory.name)
+
162
    # Collecting rendering information:
+
163
    template = "gitar/directory.html"
+
164
    context = standard_context()
+
165
    context["files"] = file_names
+
166
    context["subdirectories"] = subdirectory_names
+
167
    return render(request, template, context)
+
168
+
169
155
170
def file_viewer(request, repository_name, path, ffile):
156
171
    """ Collects the file contents of the given file path, and returns it to the
157
172
    template, with the file contents already formatted in HTML using Pygments.
158
173
    """
159
174