.gitignore 0000664 0000000 0000000 00000000433 15160672746 0013064 0 ustar 00root root 0000000 0000000 cache/
vendor/
build/
*.diff
*.err
*.orig
*.log
*.rej
*.swo
*.swp
*.zip
*.vi
*~
*.sass-cache
.DS_Store
._*
Thumbs.db
.cache
.project
.settings
.tmproj
*.esproj
nbproject
*.sublime-project
*.sublime-workspace
.hg
.svn
.CVS
.idea
node_modules
config.ini
cache.properties
composer.phar
.htaccess 0000664 0000000 0000000 00000000336 15160672746 0012674 0 ustar 00root root 0000000 0000000
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
order allow,deny
deny from all
.travis.yml 0000664 0000000 0000000 00000000234 15160672746 0013204 0 ustar 00root root 0000000 0000000 language: php
before_script:
- curl -s http://getcomposer.org/installer | php
- php composer.phar install --dev
php:
- 5.3
- 5.4
script: phpunit
INSTALL.md 0000664 0000000 0000000 00000003703 15160672746 0012527 0 ustar 00root root 0000000 0000000 # GitList Installation
* Download GitList from [gitlist.org](http://gitlist.org/) and decompress to your `/var/www/gitlist` folder, or anywhere else you want to place GitList.
* Rename the `config.ini-example` file to `config.ini`.
* Open up the `config.ini` and configure your installation. You'll have to provide where your repositories are located and the base GitList URL (in our case, http://localhost/gitlist).
* Create the cache folder and give read/write permissions to your web server user:
```
cd /var/www/gitlist
mkdir cache
chmod 777 cache
```
That's it, installation complete!
## Webserver configuration
Apache is the "default" webserver for GitList. You will find the configuration inside the `.htaccess` file. However, nginx and lighttpd are also supported.
### nginx server.conf
```
server {
server_name MYSERVER;
access_log /var/log/nginx/MYSERVER.access_log main;
error_log /var/log/nginx/MYSERVER.error_log debug_http;
root /var/www/DIR;
index index.php;
# auth_basic "Restricted";
# auth_basic_user_file rhtpasswd;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location ~* ^/index.php.*$ {
fastcgi_pass 127.0.0.1:9000;
include fastcgi.conf;
}
location / {
try_files $uri @gitlist;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
add_header Vary "Accept-Encoding";
expires max;
try_files $uri @gitlist;
tcp_nodelay off;
tcp_nopush on;
}
# location ~* \.(git|svn|patch|htaccess|log|route|plist|inc|json|pl|po|sh|ini|sample|kdev4)$ {
# deny all;
# }
location @gitlist {
rewrite ^/.*$ /index.php;
}
}
```
### lighttpd
```
# GitList is located in /var/www/gitlist
server.document-root = "/var/www"
url.rewrite-once = (
"^/gitlist/web/.+" => "$0",
"^/gitlist/favicon\.ico$" => "$0",
"^/gitlist(/[^\?]*)(\?.*)?" => "/gitlist/index.php$1$2"
)
``` LICENSE.txt 0000664 0000000 0000000 00000002705 15160672746 0012723 0 ustar 00root root 0000000 0000000 Copyright (c) 2012, Klaus Silveira and contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of GitList nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
README.md 0000664 0000000 0000000 00000012034 15160672746 0012353 0 ustar 00root root 0000000 0000000 # GitList: an elegant and modern git repository viewer
[](http://travis-ci.org/klaussilveira/gitlist)
GitList is an elegant and modern web interface for interacting with multiple git repositories. It allows you to browse repositories using your favorite browser, viewing files under different revisions, commit history, diffs. It also generates RSS feeds for each repository, allowing you to stay up-to-date with the latest changes anytime, anywhere. GitList was written in PHP, on top of the [Silex](http://silex.sensiolabs.org/) microframework and powered by the Twig template engine. This means that GitList is easy to install and easy to customize. Also, the GitList gorgeous interface was made possible due to [Bootstrap](http://twitter.github.com/bootstrap/).
## Features
* Multiple repository support
* Multiple branch support
* Multiple tag support
* Commit history, blame, diff
* RSS feeds
* Syntax highlighting
* Repository statistics
## Screenshots
[](http://cloud.github.com/downloads/klaussilveira/gitlist/1.jpg)
[](http://cloud.github.com/downloads/klaussilveira/gitlist/2.jpg)
[](http://cloud.github.com/downloads/klaussilveira/gitlist/3.jpg)
[](http://cloud.github.com/downloads/klaussilveira/gitlist/4.jpg)
[](http://cloud.github.com/downloads/klaussilveira/gitlist/5.jpg)
You can also see a live demo [here](http://git.gofedora.com).
## Authors and contributors
* [Klaus Silveira](http://www.klaussilveira.com) (Creator, developer)
## License
[New BSD license](http://www.opensource.org/licenses/bsd-license.php)
## Todo
* improve the current test code coverage
* test the interface
* error handling can be greatly improved during parsing
* submodule support
* multilanguage support
## Requirements
In order to run GitList on your server, you'll need:
* git
* Apache with mod_rewrite enabled or nginx
* PHP 5.3.3
## Installing
* Download GitList from [gitlist.org](http://gitlist.org/) and decompress to your `/var/www/gitlist` folder, or anywhere else you want to place GitList.
* Rename the `config.ini-example` file to `config.ini`.
* Open up the `config.ini` and configure your installation. You'll have to provide where your repositories are located and the base GitList URL (in our case, http://localhost/gitlist).
* Create the cache folder and give read/write permissions to your web server user:
```
cd /var/www/gitlist
mkdir cache
chmod 777 cache
```
That's it, installation complete! If you're having problems, check this [tutorial](http://gofedora.com/insanely-awesome-web-interface-git-repos/) by Kulbir Saini or the [Troubleshooting](https://github.com/klaussilveira/gitlist/wiki/Troubleshooting) page.
## Building
GitList uses [Composer](http://getcomposer.org/) to manage dependencies and [Ant](http://ant.apache.org/) to build the project. In order to run all the targets in the build script, you will need [PHPUnit](http://www.phpunit.de/), [phpcpd](https://github.com/sebastianbergmann/phpcpd), [phploc](https://github.com/sebastianbergmann/phploc), [PHPMD](http://phpmd.org/) and [PHP_Depend](http://pdepend.org).
Once you have all the dependencies set, you can clone the repository and run Ant:
```
git clone https://github.com/klaussilveira/gitlist.git
ant
```
If you just want to get the project dependencies, instead of building everything:
```
git clone https://github.com/klaussilveira/gitlist.git
curl -s http://getcomposer.org/installer | php
php composer.phar install
```
If you have Composer in your path, things get easier. But you know the drill.
## Contributing
If you are a developer, we need your help. GitList is a young project and we have lot's of stuff to do. Some developers are contributing with new features, others with bug fixes. But you can also dedicate yourself to refactoring the current codebase and improving what we already have. This is very important, we want GitList to be a state-of-the-art application, and we need your help for that.
* Stay tuned to possible bugs, suboptimal code, duplicated code, overcomplicated expressions and unused code with [PHPMD](http://ci.gitlist.org:8080/job/GitList%20\(master\)/9/pmdResult/?) in our CI server
* Try to fix any [violations](http://ci.gitlist.org:8080/job/GitList%20\(master\)/violations/) reported
* Improve the [test coverage](http://ci.gitlist.org:8080/job/GitList%20\(master\)/9/cloverphp-report/) by creating unit and functional tests
## Further information
If you want to know more about customizing GitList, check the [Customization](https://github.com/klaussilveira/gitlist/wiki/Customizing) page on the wiki. Also, if you're having problems with GitList, check the [Troubleshooting](https://github.com/klaussilveira/gitlist/wiki/Troubleshooting) page. Don't forget to report issues and suggest new features! :)
boot.php 0000664 0000000 0000000 00000001065 15160672746 0012552 0 ustar 00root root 0000000 0000000 set('git', 'repositories', rtrim($config->get('git', 'repositories'), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR);
// Startup and configure Silex application
$app = new GitList\Application($config, __DIR__);
// Mount the controllers
$app->mount('', new GitList\Controller\MainController());
$app->mount('', new GitList\Controller\BlobController());
$app->mount('', new GitList\Controller\CommitController());
$app->mount('', new GitList\Controller\TreeController());
return $app;
build.xml 0000664 0000000 0000000 00000006463 15160672746 0012726 0 ustar 00root root 0000000 0000000
cache/ 0000775 0000000 0000000 00000000000 15160672746 0012137 5 ustar 00root root 0000000 0000000 cache/.gitkeep 0000664 0000000 0000000 00000000000 15160672746 0013556 0 ustar 00root root 0000000 0000000 composer.json 0000664 0000000 0000000 00000000660 15160672746 0013620 0 ustar 00root root 0000000 0000000 {
"require": {
"silex/silex": "1.0.*",
"twig/twig": "1.9.*",
"symfony/twig-bridge": "2.1.*",
"symfony/filesystem": "2.1.*",
"klaussilveira/gitter": "0.1.1"
},
"require-dev": {
"symfony/browser-kit": "2.1.*",
"symfony/css-selector": "2.1.*"
},
"minimum-stability": "dev",
"autoload": {
"psr-0": {
"GitList": "src/"
}
}
}
composer.lock 0000664 0000000 0000000 00000062020 15160672746 0013575 0 ustar 00root root 0000000 0000000 {
"hash": "b7ee6754cba1641ef8c2b01dfdd977fd",
"packages": [
{
"name": "klaussilveira/gitter",
"version": "0.1.1",
"source": {
"type": "git",
"url": "https://github.com/klaussilveira/gitter",
"reference": "0.1.1"
},
"dist": {
"type": "zip",
"url": "https://github.com/klaussilveira/gitter/zipball/0.1.1",
"reference": "0.1.1",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"symfony/process": "2.1.*"
},
"require-dev": {
"symfony/filesystem": "2.1.*"
},
"time": "2012-09-19 12:31:50",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"Gitter": "lib/"
}
},
"license": [
"BSD-2-Clause"
],
"authors": [
{
"name": "Klaus Silveira",
"email": "klaussilveira@php.net",
"homepage": "http://www.klaussilveira.com/",
"role": "Developer"
}
],
"description": "Gitter allows you to interact in an object oriented manner with Git repositories.",
"homepage": "https://github.com/klaussilveira/gitter",
"keywords": [
"git",
"vcs"
]
},
{
"name": "pimple/pimple",
"version": "dev-master",
"source": {
"type": "git",
"url": "git://github.com/fabpot/Pimple.git",
"reference": "b9f27b8dc18c08f00627dec02359b46a24791dc3"
},
"dist": {
"type": "zip",
"url": "https://github.com/fabpot/Pimple/zipball/b9f27b8dc18c08f00627dec02359b46a24791dc3",
"reference": "b9f27b8dc18c08f00627dec02359b46a24791dc3",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "1347278988",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Pimple": "lib/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
"homepage": "http://pimple.sensiolabs.org",
"keywords": [
"dependency injection",
"container"
]
},
{
"name": "silex/silex",
"version": "dev-master",
"source": {
"type": "git",
"url": "git://github.com/fabpot/Silex.git",
"reference": "78efb9a6bef34e4547e937066707ee338f516698"
},
"dist": {
"type": "zip",
"url": "https://github.com/fabpot/Silex/zipball/78efb9a6bef34e4547e937066707ee338f516698",
"reference": "78efb9a6bef34e4547e937066707ee338f516698",
"shasum": ""
},
"require": {
"symfony/event-dispatcher": "2.1.*",
"symfony/http-foundation": "2.1.*",
"symfony/http-kernel": "2.1.*",
"symfony/routing": "2.1.*",
"php": ">=5.3.3",
"pimple/pimple": "1.*"
},
"require-dev": {
"symfony/form": "2.1.*",
"symfony/translation": "2.1.*",
"symfony/twig-bridge": "2.1.*",
"symfony/validator": "2.1.*",
"symfony/monolog-bridge": "2.1.*",
"symfony/browser-kit": "2.1.*",
"symfony/css-selector": "2.1.*",
"symfony/finder": "2.1.*",
"symfony/process": "2.1.*",
"symfony/security": "2.1.*",
"monolog/monolog": ">=1.0.0,<1.2-dev",
"symfony/config": "2.1.*",
"symfony/locale": "2.1.*",
"twig/twig": ">=1.8.0,<2.0-dev",
"swiftmailer/swiftmailer": "4.2.*",
"doctrine/dbal": "2.2.*"
},
"suggest": {
"symfony/browser-kit": "2.1.*",
"symfony/css-selector": "2.1.*",
"symfony/dom-crawler": "2.1.*"
},
"time": "1348027658",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Silex": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Igor Wiedler",
"email": "igor@wiedler.ch",
"homepage": "http://wiedler.ch/igor/"
}
],
"description": "The PHP micro-framework based on the Symfony2 Components",
"homepage": "http://silex.sensiolabs.org",
"keywords": [
"microframework"
]
},
{
"name": "symfony/event-dispatcher",
"version": "2.1.x-dev",
"target-dir": "Symfony/Component/EventDispatcher",
"source": {
"type": "git",
"url": "https://github.com/symfony/EventDispatcher",
"reference": "v2.1.1"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/EventDispatcher/zipball/v2.1.1",
"reference": "v2.1.1",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"symfony/dependency-injection": "2.1.*"
},
"suggest": {
"symfony/dependency-injection": "2.1.*",
"symfony/http-kernel": "2.1.*"
},
"time": "1347274422",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Component\\EventDispatcher": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony EventDispatcher Component",
"homepage": "http://symfony.com"
},
{
"name": "symfony/filesystem",
"version": "2.1.x-dev",
"target-dir": "Symfony/Component/Filesystem",
"source": {
"type": "git",
"url": "https://github.com/symfony/Filesystem",
"reference": "v2.1.0-RC2"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/Filesystem/zipball/v2.1.0-RC2",
"reference": "v2.1.0-RC2",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"time": "1345643321",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Component\\Filesystem": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony Filesystem Component",
"homepage": "http://symfony.com"
},
{
"name": "symfony/http-foundation",
"version": "2.1.x-dev",
"target-dir": "Symfony/Component/HttpFoundation",
"source": {
"type": "git",
"url": "https://github.com/symfony/HttpFoundation",
"reference": "23f68b488570def9ebe874a748410285f9a4acc9"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/HttpFoundation/zipball/23f68b488570def9ebe874a748410285f9a4acc9",
"reference": "23f68b488570def9ebe874a748410285f9a4acc9",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"time": "1347984592",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Component\\HttpFoundation": "",
"SessionHandlerInterface": "Symfony/Component/HttpFoundation/Resources/stubs"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony HttpFoundation Component",
"homepage": "http://symfony.com"
},
{
"name": "symfony/http-kernel",
"version": "2.1.x-dev",
"target-dir": "Symfony/Component/HttpKernel",
"source": {
"type": "git",
"url": "https://github.com/symfony/HttpKernel",
"reference": "52820d9f3b80e3b8d31aba53bb792ec25894e092"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/HttpKernel/zipball/52820d9f3b80e3b8d31aba53bb792ec25894e092",
"reference": "52820d9f3b80e3b8d31aba53bb792ec25894e092",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"symfony/event-dispatcher": "2.1.*",
"symfony/http-foundation": "2.1.*"
},
"require-dev": {
"symfony/browser-kit": "2.1.*",
"symfony/class-loader": "2.1.*",
"symfony/config": "2.1.*",
"symfony/console": "2.1.*",
"symfony/dependency-injection": "2.1.*",
"symfony/finder": "2.1.*",
"symfony/process": "2.1.*",
"symfony/routing": "2.1.*"
},
"suggest": {
"symfony/browser-kit": "2.1.*",
"symfony/class-loader": "2.1.*",
"symfony/config": "2.1.*",
"symfony/console": "2.1.*",
"symfony/dependency-injection": "2.1.*",
"symfony/finder": "2.1.*"
},
"time": "1347914517",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Component\\HttpKernel": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony HttpKernel Component",
"homepage": "http://symfony.com"
},
{
"name": "symfony/process",
"version": "2.1.x-dev",
"target-dir": "Symfony/Component/Process",
"source": {
"type": "git",
"url": "https://github.com/symfony/Process",
"reference": "c1a8adcce9ea176c3a725269603045f80c027f36"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/Process/zipball/c1a8adcce9ea176c3a725269603045f80c027f36",
"reference": "c1a8adcce9ea176c3a725269603045f80c027f36",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"time": "1348007849",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Component\\Process": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony Process Component",
"homepage": "http://symfony.com"
},
{
"name": "symfony/routing",
"version": "2.1.x-dev",
"target-dir": "Symfony/Component/Routing",
"source": {
"type": "git",
"url": "https://github.com/symfony/Routing",
"reference": "v2.1.1"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/Routing/zipball/v2.1.1",
"reference": "v2.1.1",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"symfony/config": "2.1.*",
"symfony/yaml": "2.1.*",
"symfony/http-kernel": "2.1.*",
"doctrine/common": ">=2.2,<2.4-dev"
},
"suggest": {
"doctrine/common": ">=2.2,<2.4-dev",
"symfony/config": "2.1.*",
"symfony/yaml": "2.1.*"
},
"time": "1347274422",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Component\\Routing": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony Routing Component",
"homepage": "http://symfony.com"
},
{
"name": "symfony/twig-bridge",
"version": "2.1.x-dev",
"target-dir": "Symfony/Bridge/Twig",
"source": {
"type": "git",
"url": "https://github.com/symfony/TwigBridge",
"reference": "v2.1.1"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/TwigBridge/zipball/v2.1.1",
"reference": "v2.1.1",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"twig/twig": ">=1.9.1,<2.0-dev"
},
"require-dev": {
"symfony/form": "2.1.*",
"symfony/routing": "2.1.*",
"symfony/templating": "2.1.*",
"symfony/translation": "2.1.*",
"symfony/yaml": "2.1.*",
"symfony/security": "2.1.*"
},
"suggest": {
"symfony/form": "2.1.*",
"symfony/routing": "2.1.*",
"symfony/templating": "2.1.*",
"symfony/translation": "2.1.*",
"symfony/yaml": "2.1.*",
"symfony/security": "2.1.*"
},
"time": "1347274422",
"type": "symfony-bridge",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Bridge\\Twig": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony Twig Bridge",
"homepage": "http://symfony.com"
},
{
"name": "twig/twig",
"version": "v1.9.2",
"source": {
"type": "git",
"url": "git://github.com/fabpot/Twig.git",
"reference": "v1.9.2"
},
"dist": {
"type": "zip",
"url": "https://github.com/fabpot/Twig/zipball/v1.9.2",
"reference": "v1.9.2",
"shasum": ""
},
"require": {
"php": ">=5.2.4"
},
"time": "2012-08-25 17:32:57",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
},
"license": [
"BSD-3"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
]
}
],
"packages-dev": [
{
"name": "symfony/browser-kit",
"version": "2.1.x-dev",
"target-dir": "Symfony/Component/BrowserKit",
"source": {
"type": "git",
"url": "https://github.com/symfony/BrowserKit",
"reference": "v2.1.1"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/BrowserKit/zipball/v2.1.1",
"reference": "v2.1.1",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"symfony/dom-crawler": "2.1.*"
},
"require-dev": {
"symfony/process": "2.1.*",
"symfony/css-selector": "2.1.*"
},
"suggest": {
"symfony/process": "2.1.*"
},
"time": "1347274422",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Component\\BrowserKit": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony BrowserKit Component",
"homepage": "http://symfony.com"
},
{
"name": "symfony/css-selector",
"version": "2.1.x-dev",
"target-dir": "Symfony/Component/CssSelector",
"source": {
"type": "git",
"url": "https://github.com/symfony/CssSelector",
"reference": "v2.1.0-RC2"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/CssSelector/zipball/v2.1.0-RC2",
"reference": "v2.1.0-RC2",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"time": "1345643321",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Component\\CssSelector": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony CssSelector Component",
"homepage": "http://symfony.com"
},
{
"name": "symfony/dom-crawler",
"version": "2.1.x-dev",
"target-dir": "Symfony/Component/DomCrawler",
"source": {
"type": "git",
"url": "https://github.com/symfony/DomCrawler",
"reference": "v2.1.1"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/DomCrawler/zipball/v2.1.1",
"reference": "v2.1.1",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"symfony/css-selector": "2.1.*"
},
"suggest": {
"symfony/css-selector": "2.1.*"
},
"time": "1347274422",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"autoload": {
"psr-0": {
"Symfony\\Component\\DomCrawler": ""
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
}
],
"description": "Symfony DomCrawler Component",
"homepage": "http://symfony.com"
}
],
"aliases": [
],
"minimum-stability": "dev",
"stability-flags": [
]
}
config.ini-example 0000664 0000000 0000000 00000000622 15160672746 0014473 0 ustar 00root root 0000000 0000000 [git]
client = '/usr/bin/git' ; Your git executable path
repositories = '/var/www/projects/' ; Path to your repositories
; You can hide repositories from GitList, just copy this for each repository you want to hide
; hidden[] = '/var/www/projects/BetaTest'
[app]
debug = false
; If you need to specify custom filetypes for certain extensions, do this here
[filetypes]
; extension = type
; dist = xml index.php 0000664 0000000 0000000 00000000221 15160672746 0012707 0 ustar 00root root 0000000 0000000 run(); phpunit.xml.dist 0000664 0000000 0000000 00000001350 15160672746 0014246 0 ustar 00root root 0000000 0000000
./tests/
src/ 0000775 0000000 0000000 00000000000 15160672746 0011663 5 ustar 00root root 0000000 0000000 src/GitList/ 0000775 0000000 0000000 00000000000 15160672746 0013242 5 ustar 00root root 0000000 0000000 src/GitList/Application.php 0000664 0000000 0000000 00000004243 15160672746 0016221 0 ustar 00root root 0000000 0000000 get('app', 'debug');
$this['filetypes'] = $config->getSection('filetypes');
$this['cache.archives'] = $root . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'archives';
// Register services
$this->register(new TwigServiceProvider(), array(
'twig.path' => $root . DIRECTORY_SEPARATOR . 'views',
'twig.options' => array('cache' => $root . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'views'),
));
$this->register(new GitServiceProvider(), array(
'git.client' => $config->get('git', 'client'),
'git.repos' => $config->get('git', 'repositories'),
'git.hidden' => $config->get('git', 'hidden') ? $config->get('git', 'hidden') : array(),
));
$this->register(new ViewUtilServiceProvider());
$this->register(new RepositoryUtilServiceProvider());
$this->register(new UrlGeneratorServiceProvider());
$this['twig'] = $this->share($this->extend('twig', function($twig, $app) {
$twig->addFilter('md5', new \Twig_Filter_Function('md5'));
return $twig;
}));
// Handle errors
$this->error(function (\Exception $e, $code) use ($app) {
if ($app['debug']) {
return;
}
return $app['twig']->render('error.twig', array(
'message' => $e->getMessage(),
));
});
}
}
src/GitList/Config.php 0000664 0000000 0000000 00000002207 15160672746 0015161 0 ustar 00root root 0000000 0000000 data = parse_ini_file('config.ini', true);
$this->validateOptions();
}
public function get($section, $option)
{
if (!array_key_exists($section, $this->data)) {
return false;
}
if (!array_key_exists($option, $this->data[$section])) {
return false;
}
return $this->data[$section][$option];
}
public function getSection($section)
{
if (!array_key_exists($section, $this->data)) {
return false;
}
return $this->data[$section];
}
public function set($section, $option, $value)
{
$this->data[$section][$option] = $value;
}
protected function validateOptions()
{
if (!$this->get('git', 'repositories') || !is_dir($this->get('git', 'repositories'))) {
die("Please, edit the config.ini file and provide your repositories directory");
}
}
} src/GitList/Controller/ 0000775 0000000 0000000 00000000000 15160672746 0015365 5 ustar 00root root 0000000 0000000 src/GitList/Controller/BlobController.php 0000664 0000000 0000000 00000003471 15160672746 0021025 0 ustar 00root root 0000000 0000000 get('{repo}/blob/{branch}/{file}', function($repo, $branch, $file) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
$blob = $repository->getBlob("$branch:\"$file\"");
$breadcrumbs = $app['util.view']->getBreadcrumbs($file);
$fileType = $app['util.repository']->getFileType($file);
return $app['twig']->render('file.twig', array(
'file' => $file,
'fileType' => $fileType,
'blob' => $blob->output(),
'repo' => $repo,
'branch' => $branch,
'breadcrumbs' => $breadcrumbs,
'branches' => $repository->getBranches(),
'tags' => $repository->getTags(),
));
})->assert('file', '.+')
->assert('repo', '[\w-._]+')
->assert('branch', '[\w-._]+')
->bind('blob');
$route->get('{repo}/raw/{branch}/{file}', function($repo, $branch, $file) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
$blob = $repository->getBlob("$branch:\"$file\"")->output();
return new Response($blob, 200, array('Content-Type' => 'text/plain'));
})->assert('file', '.+')
->assert('repo', '[\w-._]+')
->assert('branch', '[\w-._]+')
->bind('blob_raw');
return $route;
}
} src/GitList/Controller/CommitController.php 0000664 0000000 0000000 00000007657 15160672746 0021411 0 ustar 00root root 0000000 0000000 get('{repo}/commits/{branch}/{file}', function($repo, $branch, $file) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
$type = $file ? "$branch -- $file" : $branch;
$pager = $app['util.view']->getPager($app['request']->get('page'), $repository->getTotalCommits($type));
$commits = $repository->getPaginatedCommits($type, $pager['current']);
foreach ($commits as $commit) {
$date = $commit->getDate();
$date = $date->format('m/d/Y');
$categorized[$date][] = $commit;
}
$template = $app['request']->isXmlHttpRequest() ? 'commits_list.twig' : 'commits.twig';
return $app['twig']->render($template, array(
'pager' => $pager,
'repo' => $repo,
'branch' => $branch,
'branches' => $repository->getBranches(),
'tags' => $repository->getTags(),
'commits' => $categorized,
'file' => $file,
));
})->assert('repo', '[\w-._]+')
->assert('branch', '[\w-._]+')
->assert('file', '.+')
->value('branch', 'master')
->value('file', '')
->bind('commits');
$route->post('{repo}/commits/search', function(Request $request, $repo) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
$commits = $repository->searchCommitLog($request->get('query'));
foreach ($commits as $commit) {
$date = $commit->getDate();
$date = $date->format('m/d/Y');
$categorized[$date][] = $commit;
}
return $app['twig']->render('searchcommits.twig', array(
'repo' => $repo,
'branch' => 'master',
'file' => '',
'commits' => $categorized,
'branches' => $repository->getBranches(),
'tags' => $repository->getTags(),
));
})->assert('repo', '[\w-._]+')
->bind('searchcommits');
$route->get('{repo}/commit/{commit}/', function($repo, $commit) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
$commit = $repository->getCommit($commit);
return $app['twig']->render('commit.twig', array(
'branch' => 'master',
'repo' => $repo,
'commit' => $commit,
));
})->assert('repo', '[\w-._]+')
->assert('commit', '[a-f0-9^]+')
->bind('commit');
$route->get('{repo}/blame/{branch}/{file}', function($repo, $branch, $file) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
$blames = $repository->getBlame("$branch -- $file");
return $app['twig']->render('blame.twig', array(
'file' => $file,
'repo' => $repo,
'branch' => $branch,
'branches' => $repository->getBranches(),
'tags' => $repository->getTags(),
'blames' => $blames,
));
})->assert('repo', '[\w-._]+')
->assert('file', '.+')
->assert('branch', '[\w-._]+')
->bind('blame');
return $route;
}
} src/GitList/Controller/MainController.php 0000664 0000000 0000000 00000004072 15160672746 0021031 0 ustar 00root root 0000000 0000000 get('/', function() use ($app) {
$repositories = $app['git']->getRepositories($app['git.repos']);
return $app['twig']->render('index.twig', array(
'repositories' => $repositories,
));
})->bind('homepage');
$route->get('{repo}/stats/{branch}', function($repo, $branch) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
$stats = $repository->getStatistics($branch);
$authors = $repository->getAuthorStatistics();
return $app['twig']->render('stats.twig', array(
'repo' => $repo,
'branch' => $branch,
'branches' => $repository->getBranches(),
'tags' => $repository->getTags(),
'stats' => $stats,
'authors' => $authors,
));
})->assert('repo', '[\w-._]+')
->assert('branch', '[\w-._]+')
->value('branch', 'master')
->bind('stats');
$route->get('{repo}/{branch}/rss/', function($repo, $branch) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
$commits = $repository->getPaginatedCommits($branch);
$html = $app['twig']->render('rss.twig', array(
'repo' => $repo,
'branch' => $branch,
'commits' => $commits,
));
return new Response($html, 200, array('Content-Type' => 'application/rss+xml'));
})->assert('repo', '[\w-._]+')
->assert('branch', '[\w-._]+')
->bind('rss');
return $route;
}
} src/GitList/Controller/TreeController.php 0000664 0000000 0000000 00000011143 15160672746 0021041 0 ustar 00root root 0000000 0000000 get('{repo}/tree/{branch}/{tree}/', $treeController = function($repo, $branch = '', $tree = '') use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
if (!$branch) {
$branch = $repository->getHead();
}
$files = $repository->getTree($tree ? "$branch:\"$tree\"/" : $branch);
$breadcrumbs = $app['util.view']->getBreadcrumbs($tree);
$parent = null;
if (($slash = strrpos($tree, '/')) !== false) {
$parent = substr($tree, 0, $slash);
} elseif (!empty($tree)) {
$parent = '';
}
return $app['twig']->render('tree.twig', array(
'files' => $files->output(),
'repo' => $repo,
'branch' => $branch,
'path' => $tree ? $tree . '/' : $tree,
'parent' => $parent,
'breadcrumbs' => $breadcrumbs,
'branches' => $repository->getBranches(),
'tags' => $repository->getTags(),
'readme' => $app['util.repository']->getReadme($repo, $branch),
));
})->assert('repo', '[\w-._]+')
->assert('branch', '[\w-._]+')
->assert('tree', '.+')
->bind('tree');
$route->post('{repo}/tree/{branch}/search', function(Request $request, $repo, $branch = '', $tree = '') use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
if (!$branch) {
$branch = $repository->getHead();
}
$breadcrumbs = $app['util.view']->getBreadcrumbs($tree);
$results = $repository->searchTree($request->get('query'), $branch);
return $app['twig']->render('search.twig', array(
'results' => $results,
'repo' => $repo,
'branch' => $branch,
'path' => $tree,
'breadcrumbs' => $breadcrumbs,
'branches' => $repository->getBranches(),
'tags' => $repository->getTags(),
));
})->assert('repo', '[\w-._]+')
->assert('branch', '[\w-._]+')
->bind('search');
$route->get('{repo}/{branch}/', function($repo, $branch) use ($app, $treeController) {
return $treeController($repo, $branch);
})->assert('repo', '[\w-._]+')
->assert('branch', '[\w-._]+')
->bind('branch');
$route->get('{repo}/', function($repo) use ($app, $treeController) {
return $treeController($repo);
})->assert('repo', '[\w-._]+')
->bind('repository');
$route->get('{repo}/{format}ball/{branch}', function($repo, $format, $branch) use ($app) {
$repository = $app['git']->getRepository($app['git.repos'] . $repo);
$tree = $repository->getBranchTree($branch);
if (false === $tree) {
return $app->abort(404, 'Invalid commit or tree reference: ' . $branch);
}
$file = $app['cache.archives'] . DIRECTORY_SEPARATOR
. $repo . DIRECTORY_SEPARATOR
. substr($tree, 0, 2) . DIRECTORY_SEPARATOR
. substr($tree, 2)
. '.'
. $format;
if (!file_exists($file)) {
$repository->createArchive($tree, $file, $format);
}
return new StreamedResponse(function () use ($file) {
readfile($file);
}, 200, array(
'Content-type' => ('zip' === $format) ? 'application/zip' : 'application/x-tar',
'Content-Description' => 'File Transfer',
'Content-Disposition' => 'attachment; filename="'.$repo.'-'.substr($tree, 0, 6).'.'.$format.'"',
'Content-Transfer-Encoding' => 'binary',
));
})->assert('format', '(zip|tar)')
->assert('repo', '[\w-._]+')
->assert('branch', '[\w-._]+')
->bind('archive');
return $route;
}
} src/GitList/Exception/ 0000775 0000000 0000000 00000000000 15160672746 0015200 5 ustar 00root root 0000000 0000000 src/GitList/Exception/BlankDataException.php 0000664 0000000 0000000 00000000132 15160672746 0021405 0 ustar 00root root 0000000 0000000 create($bare);
}
/**
* Opens a repository at the specified path
*
* @param string $path Path where the repository is located
* @return Repository Instance of Repository
*/
public function getRepository($path)
{
if (!file_exists($path) || !file_exists($path . '/.git/HEAD') && !file_exists($path . '/HEAD')) {
throw new \RuntimeException('There is no GIT repository at ' . $path);
}
if (in_array($path, $this->getHidden())) {
throw new \RuntimeException('You don\'t have access to this repository');
}
return new Repository($path, $this);
}
} src/GitList/Git/Repository.php 0000664 0000000 0000000 00000011023 15160672746 0016652 0 ustar 00root root 0000000 0000000 %H%h%T%P%an%ae%at%cn%ce%ct'";
if ($file) {
$command .= " $file";
}
$logs = $this->getPrettyFormat($command);
foreach ($logs as $log) {
$commit = new Commit;
$commit->importData($log);
$commits[] = $commit;
}
return $commits;
}
public function searchCommitLog($query)
{
$command = "log --grep='$query' --pretty=format:'- %H%h%T%P%an%ae%at%cn%ce%ct
'";
$logs = $this->getPrettyFormat($command);
foreach ($logs as $log) {
$commit = new Commit;
$commit->importData($log);
$commits[] = $commit;
}
return $commits;
}
public function searchTree($query, $branch)
{
try {
$results = $this->getClient()->run($this, "grep -I --line-number '$query' $branch");
} catch (\RuntimeException $e) {
return false;
}
$results = explode("\n", $results);
foreach ($results as $result) {
if ($result == '') {
continue;
}
preg_match_all('/([\w-._]+):(.+):([0-9]+):(.+)/', $result, $matches, PREG_SET_ORDER);
$data['branch'] = $matches[0][1];
$data['file'] = $matches[0][2];
$data['line'] = $matches[0][3];
$data['match'] = $matches[0][4];
$searchResults[] = $data;
}
return $searchResults;
}
public function getAuthorStatistics()
{
$logs = $this->getClient()->run($this, 'log --pretty=format:"%an||%ae" ' . $this->getHead());
if (empty($logs)) {
throw new \RuntimeException('No statistics available');
}
$logs = explode("\n", $logs);
$logs = array_count_values($logs);
arsort($logs);
foreach ($logs as $user => $count) {
$user = explode('||', $user);
$data[] = array('name' => $user[0], 'email' => $user[1], 'commits' => $count);
}
return $data;
}
public function getStatistics($branch)
{
// Calculate amount of files, extensions and file size
$logs = $this->getClient()->run($this, 'ls-tree -r -l ' . $branch);
$lines = explode("\n", $logs);
$files = array();
$data['extensions'] = array();
$data['size'] = 0;
$data['files'] = 0;
foreach ($lines as $key => $line) {
if (empty($line)) {
unset($lines[$key]);
continue;
}
$files[] = preg_split("/[\s]+/", $line);
}
foreach ($files as $file) {
if ($file[1] == 'blob') {
$data['files']++;
}
if (is_numeric($file[3])) {
$data['size'] += $file[3];
}
if (($pos = strrpos($file[4], '.')) !== FALSE) {
$data['extensions'][] = substr($file[4], $pos);
}
}
$data['extensions'] = array_count_values($data['extensions']);
arsort($data['extensions']);
return $data;
}
/**
* Create a TAR or ZIP archive of a git tree
*
* @param string $tree Tree-ish reference
* @param string $output Output File name
* @param string $format Archive format
*/
public function createArchive($tree, $output, $format = 'zip')
{
$fs = new Filesystem;
$fs->mkdir(dirname($output));
$this->getClient()->run($this, "archive --format=$format --output=$output $tree");
}
}
src/GitList/Provider/ 0000775 0000000 0000000 00000000000 15160672746 0015034 5 ustar 00root root 0000000 0000000 src/GitList/Provider/GitServiceProvider.php 0000664 0000000 0000000 00000001270 15160672746 0021324 0 ustar 00root root 0000000 0000000 share(function () use ($app) {
return new Repository($app);
});
}
public function boot(Application $app)
{
}
}
src/GitList/Provider/ViewUtilServiceProvider.php 0000664 0000000 0000000 00000001043 15160672746 0022347 0 ustar 00root root 0000000 0000000 share(function () {
return new View;
});
}
public function boot(Application $app)
{
}
}
src/GitList/Util/ 0000775 0000000 0000000 00000000000 15160672746 0014157 5 ustar 00root root 0000000 0000000 src/GitList/Util/Repository.php 0000664 0000000 0000000 00000010133 15160672746 0017045 0 ustar 00root root 0000000 0000000 'php',
'c' => 'clike',
'h' => 'clike',
'cpp' => 'clike',
'm' => 'clike',
'mm' => 'clike',
'cs' => 'text/x-csharp',
'java' => 'java',
'clj' => 'clojure',
'coffee' => 'coffeescript',
'css' => 'css',
'diff' => 'diff',
'ecl' => 'ecl',
'el' => 'erlang',
'go' => 'go',
'groovy' => 'groovy',
'hs' => 'haskell',
'lhs' => 'haskell',
'jsp' => 'htmlembedded',
'asp' => 'htmlembedded',
'aspx' => 'htmlembedded',
'html' => 'htmlmixed',
'tpl' => 'htmlmixed',
'js' => 'javascript',
'json' => 'javascript',
'less' => 'less',
'lua' => 'lua',
'md' => 'markdown',
'markdown' => 'markdown',
'sql' => 'mysql',
'pl' => 'perl',
'pm' => 'perl',
'pas' => 'pascal',
'ini' => 'properties',
'cfg' => 'properties',
'nt' => 'ntriples',
'py' => 'python',
'rb' => 'ruby',
'rst' => 'rst',
'r' => 'r',
'sh' => 'shell',
'ss' => 'scheme',
'scm' => 'scheme',
'sls' => 'scheme',
'sps' => 'scheme',
'rs' => 'rust',
'st' => 'smalltalk',
'tex' => 'stex',
'vbs' => 'vbscript',
'v' => 'verilog',
'xml' => 'xml',
'xsd' => 'xml',
'xsl' => 'xml',
'xul' => 'xml',
'xlf' => 'xml',
'xliff' => 'xml',
'xaml' => 'xml',
'wxs' => 'xml',
'wxl' => 'xml',
'wxi' => 'xml',
'wsdl' => 'xml',
'svg' => 'xml',
'rss' => 'xml',
'rdf' => 'xml',
'plist' => 'xml',
'mxml' => 'xml',
'kml' => 'xml',
'glade' => 'xml',
'xq' => 'xquery',
'xqm' => 'xquery',
'xquery' => 'xquery',
'xqy' => 'xquery',
'yml' => 'yaml',
'yaml' => 'yaml',
'png' => 'image',
'jpg' => 'image',
'gif' => 'image',
'jpeg' => 'image',
'bmp' => 'image',
'csproj' => 'xml',
);
public function __construct(Application $app)
{
$this->app = $app;
}
/**
* Returns the file type based on filename by treating the extension
*
* The file type is used by CodeMirror, a Javascript-based IDE implemented in
* GitList, to properly highlight the blob syntax (if it's a source-code)
*
* @param string $file File name
* @return mixed File type
*/
public function getFileType($file)
{
if (($pos = strrpos($file, '.')) !== FALSE) {
$fileType = substr($file, $pos + 1);
} else {
return 'text';
}
if (isset($this->defaultFileTypes[$fileType])) {
return $this->defaultFileTypes[$fileType];
}
if (!empty($this->app['filetypes'])) {
if (isset($this->app['filetypes'][$fileType])) {
return $this->app['filetypes'][$fileType];
}
}
return 'text';
}
public function getReadme($repo, $branch = 'master')
{
$repository = $this->app['git']->getRepository($this->app['git.repos'] . $repo);
$files = $repository->getTree($branch)->output();
foreach ($files as $file) {
if (preg_match('/^readme*/i', $file['name'])) {
return array(
'filename' => $file['name'],
'content' => $repository->getBlob("$branch:\"{$file['name']}\"")->output()
);
}
}
return array();
}
}
src/GitList/Util/View.php 0000664 0000000 0000000 00000002407 15160672746 0015605 0 ustar 00root root 0000000 0000000 $path) {
$breadcrumbs[] = array(
'dir' => $path,
'path' => implode('/', array_slice($paths, 0, $i + 1)),
);
}
return $breadcrumbs;
}
public function getPager($pageNumber, $totalCommits)
{
$pageNumber = (empty($pageNumber)) ? 0 : $pageNumber;
$lastPage = intval($totalCommits / 15);
// If total commits are integral multiple of 15, the lastPage will be commits/15 - 1.
$lastPage = ($lastPage * 15 == $totalCommits) ? $lastPage - 1 : $lastPage;
$nextPage = $pageNumber + 1;
$previousPage = $pageNumber - 1;
return array('current' => $pageNumber,
'next' => $nextPage,
'previous' => $previousPage,
'last' => $lastPage,
'total' => $totalCommits,
);
}
}
tests/ 0000775 0000000 0000000 00000000000 15160672746 0012236 5 ustar 00root root 0000000 0000000 tests/InterfaceTest.php 0000664 0000000 0000000 00000023740 15160672746 0015515 0 ustar 00root root 0000000 0000000 mkdir(self::$tmpdir);
if (!is_writable(self::$tmpdir)) {
$this->markTestSkipped('There are no write permissions in order to create test repositories.');
}
$options['path'] = getenv('GIT_CLIENT') ?: '/usr/bin/git';
$options['hidden'] = array(self::$tmpdir . '/hiddenrepo');
$git = new Client($options);
// GitTest repository fixture
$git->createRepository(self::$tmpdir . 'GitTest');
$repository = $git->getRepository(self::$tmpdir . 'GitTest');
file_put_contents(self::$tmpdir . 'GitTest/README.md', "## GitTest\nGitTest is a *test* repository!");
file_put_contents(self::$tmpdir . 'GitTest/test.php', "setConfig('user.name', 'Luke Skywalker');
$repository->setConfig('user.email', 'luke@rebel.org');
$repository->addAll();
$repository->commit("Initial commit");
$repository->createBranch('issue12');
$repository->createBranch('issue42');
// foobar repository fixture
$git->createRepository(self::$tmpdir . 'foobar');
$repository = $git->getRepository(self::$tmpdir . '/foobar');
file_put_contents(self::$tmpdir . 'foobar/bar.json', "{\n\"name\": \"foobar\"\n}");
file_put_contents(self::$tmpdir . 'foobar/.git/description', 'This is a test repo!');
$fs->mkdir(self::$tmpdir . 'foobar/myfolder');
$fs->mkdir(self::$tmpdir . 'foobar/testfolder');
file_put_contents(self::$tmpdir . 'foobar/myfolder/mytest.php', "setConfig('user.name', 'Luke Skywalker');
$repository->setConfig('user.email', 'luke@rebel.org');
$repository->addAll();
$repository->commit("First commit");
}
public function createApplication()
{
$app = require 'boot.php';
$app['debug'] = true;
$app['git.repos'] = self::$tmpdir;
return $app;
}
public function testInitialPage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/');
$this->assertTrue($client->getResponse()->isOk());
$this->assertCount(1, $crawler->filter('title:contains("GitList")'));
$this->assertCount(1, $crawler->filter('div.repository-header:contains("GitTest")'));
$this->assertEquals('/GitTest/', $crawler->filter('.repository-header a')->eq(0)->attr('href'));
$this->assertEquals('/GitTest/master/rss/', $crawler->filter('.repository-header a')->eq(1)->attr('href'));
$this->assertCount(1, $crawler->filter('div.repository-header:contains("foobar")'));
$this->assertCount(1, $crawler->filter('div.repository-body:contains("This is a test repo!")'));
$this->assertEquals('/foobar/', $crawler->filter('.repository-header a')->eq(2)->attr('href'));
$this->assertEquals('/foobar/master/rss/', $crawler->filter('.repository-header a')->eq(3)->attr('href'));
}
public function testRepositoryPage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/GitTest/');
$this->assertTrue($client->getResponse()->isOk());
$this->assertCount(1, $crawler->filter('.tree tr:contains("README.md")'));
$this->assertCount(1, $crawler->filter('.tree tr:contains("test.php")'));
$this->assertCount(1, $crawler->filter('.readme-header:contains("README.md")'));
$this->assertEquals("## GitTest\nGitTest is a *test* repository!", $crawler->filter('#readme-content')->eq(0)->text());
$this->assertEquals('/GitTest/blob/master/README.md', $crawler->filter('.tree tr td')->eq(0)->filter('a')->eq(0)->attr('href'));
$this->assertEquals('/GitTest/blob/master/test.php', $crawler->filter('.tree tr td')->eq(3)->filter('a')->eq(0)->attr('href'));
$this->assertEquals('issue12', $crawler->filter('.dropdown-menu li')->eq(1)->text());
$this->assertEquals('issue42', $crawler->filter('.dropdown-menu li')->eq(2)->text());
$this->assertEquals('master', $crawler->filter('.dropdown-menu li')->eq(3)->text());
$crawler = $client->request('GET', '/foobar/');
$this->assertTrue($client->getResponse()->isOk());
$this->assertCount(1, $crawler->filter('.tree tr:contains("myfolder")'));
$this->assertCount(1, $crawler->filter('.tree tr:contains("testfolder")'));
$this->assertCount(1, $crawler->filter('.tree tr:contains("bar.json")'));
$this->assertEquals('/foobar/tree/master/myfolder/', $crawler->filter('.tree tr td')->eq(0)->filter('a')->eq(0)->attr('href'));
$this->assertEquals('/foobar/tree/master/testfolder/', $crawler->filter('.tree tr td')->eq(3)->filter('a')->eq(0)->attr('href'));
$this->assertEquals('/foobar/blob/master/bar.json', $crawler->filter('.tree tr td')->eq(6)->filter('a')->eq(0)->attr('href'));
$this->assertCount(0, $crawler->filter('.readme-header'));
$this->assertEquals('master', $crawler->filter('.dropdown-menu li')->eq(1)->text());
}
public function testBlobPage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/GitTest/blob/master/test.php');
$this->assertTrue($client->getResponse()->isOk());
$this->assertCount(1, $crawler->filter('.breadcrumb .active:contains("test.php")'));
$this->assertEquals('/GitTest/raw/master/test.php', $crawler->filter('.source-header .btn-group a')->eq(0)->attr('href'));
$this->assertEquals('/GitTest/blame/master/test.php', $crawler->filter('.source-header .btn-group a')->eq(1)->attr('href'));
$this->assertEquals('/GitTest/commits/master/test.php', $crawler->filter('.source-header .btn-group a')->eq(2)->attr('href'));
}
public function testRawPage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/GitTest/raw/master/test.php');
$this->assertTrue($client->getResponse()->isOk());
$this->assertEquals("getResponse()->getContent());
}
public function testBlamePage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/GitTest/blame/master/test.php');
$this->assertTrue($client->getResponse()->isOk());
$this->assertCount(1, $crawler->filter('.source-header .meta:contains("test.php")'));
$this->assertRegexp('/\/GitTest\/commit\/[a-zA-Z0-9%]+\//', $crawler->filter('.blame-view .commit')->eq(0)->filter('a')->attr('href'));
$crawler = $client->request('GET', '/foobar/blame/master/bar.json');
$this->assertTrue($client->getResponse()->isOk());
$this->assertCount(1, $crawler->filter('.source-header .meta:contains("bar.json")'));
$this->assertRegexp('/\/foobar\/commit\/[a-zA-Z0-9%]+\//', $crawler->filter('.blame-view .commit')->eq(0)->filter('a')->attr('href'));
}
public function testHistoryPage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/GitTest/commits/master/test.php');
$this->assertTrue($client->getResponse()->isOk());
$this->assertEquals('Initial commit', $crawler->filter('.table tbody tr td h4')->eq(0)->text());
$crawler = $client->request('GET', '/GitTest/commits/master/README.md');
$this->assertTrue($client->getResponse()->isOk());
$this->assertEquals('Initial commit', $crawler->filter('.table tbody tr td h4')->eq(0)->text());
$crawler = $client->request('GET', '/foobar/commits/master/bar.json');
$this->assertTrue($client->getResponse()->isOk());
$this->assertEquals('First commit', $crawler->filter('.table tbody tr td h4')->eq(0)->text());
}
public function testCommitsPage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/GitTest/commits');
$this->assertTrue($client->getResponse()->isOk());
$this->assertEquals('Initial commit', $crawler->filter('.table tbody tr td h4')->eq(0)->text());
$crawler = $client->request('GET', '/foobar/commits');
$this->assertTrue($client->getResponse()->isOk());
$this->assertEquals('First commit', $crawler->filter('.table tbody tr td h4')->eq(0)->text());
}
public function testStatsPage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/GitTest/stats');
$this->assertTrue($client->getResponse()->isOk());
$this->assertRegexp('/.php: 1 files/', $crawler->filter('.table tbody')->eq(0)->text());
$this->assertRegexp('/.md: 1 files/', $crawler->filter('.table tbody')->eq(0)->text());
$this->assertRegexp('/Total files: 2/', $crawler->filter('.table tbody')->eq(0)->text());
$this->assertRegexp('/Luke Skywalker: 1 commits/', $crawler->filter('.table tbody')->eq(0)->text());
}
public function testRssPage()
{
$client = $this->createClient();
$crawler = $client->request('GET', '/GitTest/master/rss/');
$this->assertTrue($client->getResponse()->isOk());
$this->assertRegexp('/Latest commits in GitTest:master/', $client->getResponse()->getContent());
$this->assertRegexp('/Initial commit/', $client->getResponse()->getContent());
}
public static function tearDownAfterClass()
{
$fs = new Filesystem();
$fs->remove(self::$tmpdir);
}
}
views/ 0000775 0000000 0000000 00000000000 15160672746 0012231 5 ustar 00root root 0000000 0000000 views/blame.twig 0000664 0000000 0000000 00000001270 15160672746 0014205 0 ustar 00root root 0000000 0000000 {% extends 'layout_page.twig' %}
{% set page = 'commits' %}
{% block title %}GitList{% endblock %}
{% block content %}
{% include 'breadcrumb.twig' with {breadcrumbs: [{dir: 'Blame', path:''}]} %}
{% endblock %}
views/branch_menu.twig 0000664 0000000 0000000 00000001165 15160672746 0015411 0 ustar 00root root 0000000 0000000