Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

www.github.com/gitblit/gitblit.git

Package Overview
Dependencies
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

www.github.com/gitblit/gitblit.git - npm Package Compare versions

Comparing version
v1.9.1
to
v1.9.2
+81
CONTRIBUTING.md
# How to contribute
Hiii! It is lovely that you are reading this! Since Gitblit has been and still is a labour of love, it can use all the help it can get. It also means that, since this is Open Source and everyone is working on it in their limited free time, to make your contribution count, e.g. get your pull request merged, you should make it easy to review and include your contribution.
This usually works by spending some of your time and putting some effort into your contribution in order to save others the time, who have to review all the various contributions. It would be such a shame if you created a great feature or fixed a nasty bug but it is not getting included because the maintainers do not find the time to review and test your code because it is too much work.
Speaking of tests, this is certainly an area that is lacking and where help would be very appreciated. Gitblit is currently lacking test coverage, so if you would like to help to speed up development, you could add some unit tests to get more code covered by tests.
Maybe you found a bug. Then it is also great if you just open an issue in the Github issue tracker. But please make sure to include all necessary information that lets others understand what your problem is, what you encountered and actually expected, and (important!) how to reproduce it.
Maybe you found a bug and have already fixed it. Fantastic! Please make sure that you include tests in your pull request for this bug. These tests should demonstrate the bug, i.e. they should fail when run without your fix. They can then be used as regression tests to make sure that the bug does not come back.
The same is true if you added a feature and give us a pull request to get it included. Please make sure that you have covered your feature with tests. And also, update the documentation, or describe it in enough detail in your pull request so that we can update the documentation accordingly.
But wait, there are so many ways to contribute!
Maybe you see an existing issue, which you also have with Gitblit, but the existing issue is lacking details. You could triage issues, add steps how to reproduce a bug, provide more insight or even add a unit test which reproduces the bug. Also look out for issues with the label `bug triage`. These are ones we would like to fix but haven't reproduced the problem yet.
Or maybe you think that Gitblit's documentation could be improved. Well, yes, it could. You might have come across something which isn't covered in the documentation or could be clearer. Heck, there are even Github issues concerning documentation. Or you were trying to make sense of Gitblit's code and architecture and started documenting it for your understanding. Whatever it is, if it can help others, too, you could contribute it to the project, share with the community.
Or, browse through open issues and vote for the ones you would like to see fixed or implemeted because you could use it yourself, by leaving a thumbs up feedback.
Or, ....
## Pull requests
So, pull requests. Pull requests get reviewed and you can help to make this easy and faster. Which makes us happy and makes you happy. When you create a pull request, pease follow these basic rules:
Every pull request should be from a new, separate branch. Do not create multiple pull requests from the same branch. Do not create a pull request from your `master` branch. This makes it much, much harder to merge them. Why? Because you will keep adding new commits to your `master` branch which have nothing to do with the pull request. But the commits show up in the pull request.
That is why each pull request should have it's own branch, and each branch should have only one topic. That is to say each feature, fix, change set, should be on a separate branch. Maybe we totally love one of your features, but fo some reason will not add a different chnage from you. If both changes were on two branches and therefore two pull requests, the one is easy to merge. If everything is sitting on one branch and in one pull request, then we are left with the work of picking together the commits that we want to merge.
We follow a linear or semi-linear Git history. That means that your pull request should be based on the tip of our `master` (or whatever branch you choose as a target). If it isn't, chances are that we will have to rebase it onto our branch tip. Which takes time, which makes it take longer to merge ....
Tests, did I mention tests? Please remember to include a reasonable amount of test cases.
In addition to the above, if would be great if you could also keep the following in mind:
Provide enough comments in your pull request for others to understand what you changed any why. This helps with the review. Feel free to [reference any issue](https://docs.github.com/en/free-pro-team@latest/github/writing-on-github/autolinked-references-and-urls#issues-and-pull-requests) that is related.
Kindly keep your merge request in a mergeable state. If the checks run on pull requests fail, investigate why and fix it. If the main branch has moved on, it would be tops if you could rebase your changes branch and re-test, so that we don't have to do that.
## Commits
Your commits should be atomic, which is to say, put everything that belongs to that change into one commit, but only that and not more than that. The code should compile after each commit. Craft your commits so that they could be reverted individually.
You know that git allows you to clean up your commit history locally, before pushing, so that you can get rid of all the second, third and fourth try to get it right, and it looks like you wrote perfect code the first time around, do you? If you know how, feel free to clean up your branch before pushing it for a pull request.
We also love good commit messages! You may know why you did what you did in your commit, but the rest of the worl doesn't know about your genious, yet. So let us know the Why and What of your change. The How can be found in the code, but all the background is very valuable, too! Feel free to write it into the commit message, share your thoughts with us.
Remember that commit messages are like emails - with a subject line. Did you know that git commit messages are meant to be written like an email, with a subject line? It's true!
Well, others have already written about how to write good commit messages, so let's not repeat it here. If you'd like to know more, you can go and read [Chris' article](https://cbea.ms/git-commit/).
## Coding conventions
Gitblit's code has a bit of a mix of styles. It would be easier to digest for everyone and less time-consuming to review and understand, if it would follow a single, common code style. But at least please do not mix different styles in one file. So the first important rule is:
* Keep the style in existing files and use it for code that you add. Do not mix different code styles (braces, naming, casing) in one file.
If you create new files, it would be great if you could adhere to the following for Java code, to establish a common style going forward:
* Indentation is four spaces. No tabs.
* Sun Java code style
* A `if`, `while` etc. block with only one statement either uses braces around the statement, or it is all on one line.
This is open source software. Your code will be public and read by many others. Please consider the people who will read your code, and make it look nice and easy to follow for them.
Pleease, do never mix actual functional changes with reformatting or lines with just changed indentation or whitespace in one commit. This makes it very hard to figure out what the actual changes are. Which means it takes longer to review, which means merging the pull request is delayed, .... the lot. If something requires whitespace changes, they should be in their own commit. Mention that in the commit message.
Actually, [do not reformat entire files](https://github.com/rails/rails/pull/13771#issuecomment-32746700).
----
All in all, you should have fun and feel good contributing. So if the above is too much to ask, we would still like your contributions. But it will make it harder for us to include them and thus take a long time and make things slower. These rules are made so that the workload is shared among everyone, since developing software is not only the fun and exciting part but also includes the necessary more mundane tasks.
#このファイルは、他の翻訳ファイルと違いこのファイル名のままでは動作しない。
#_ja は便宜上付けている名前で、projects.conf に改名し、既存の projects.conf と置き換えて初めて動作する。
[project "main"]
title = メインリポジトリ
description = 共有リポジトリ群
#!/bin/bash
sudo cp service-freebsd.sh /usr/local/etc/rc.d/gitblit
#!/bin/sh
# PROVIDE: gitblit
# BEFORE: LOGIN
# KEYWORD: shutdown
PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
. /etc/rc.subr
name="gitblit"
rcvar="gitblit_enable"
pidfile="/var/run/${name}.pid"
start_cmd="${name}_start"
stop_cmd="${name}_stop"
restart_cmd="${name}_restart"
# change theses values (default values)
GITBLIT_PATH=/opt/gitblit
GITBLIT_BASE_FOLDER=/opt/gitblit/data
. ${GITBLIT_PATH}/java-proxy-config.sh
COMMAND_LINE="java -server -Xmx1024M ${JAVA_PROXY_CONFIG} -Djava.awt.headless=true -cp gitblit.jar:ext/* com.gitblit.GitBlitServer --baseFolder $GITBLIT_BASE_FOLDER"
gitblit_start()
{
echo "Starting Gitblit Server..."
cd $GITBLIT_PATH
$COMMAND_LINE --dailyLogFile &
}
gitblit_stop()
{
echo "Stopping Gitblit Server..."
cd $GITBLIT_PATH
$COMMAND_LINE --stop > /dev/null &
}
gitblit_restart()
{
$0 stop
sleep 5
$0 start
}
load_rc_config $name
run_rc_command "$1"
/*
* Copyright 2021 gitblit.com, Ingo Lafrenz
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gitblit;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* Simple class with the only purpose to save the realm file (users.conf) in
* a fast efficient manner. The JGit Config classes used previously caused
* a massive CPU hog if the users file got bigger than about 30000 lines.
*
* @author Ingo Lafrenz
*
*/
public class StoredUserConfig {
private final File realmFileCopy;
private SortedMap<String, Section> sections = new TreeMap<>();
public StoredUserConfig(File realmFileCopy) {
this.realmFileCopy = realmFileCopy;
}
public void setString(final String section, final String subsection, String name, String value) {
String key = generateKey(section, subsection);
Section s = sections.get(key);
if (s == null) {
s = new Section(section, subsection);
sections.put(key, s);
}
s.addEntry(name, value);
}
public void setBoolean(String section, String subsection, String name, boolean value) {
setString(section, subsection, name, String.valueOf(value));
}
public void setStringList(String section, String subsection, String name, List<String> list) {
for (String value : list) {
setString(section, subsection, name, value);
}
}
public void save() throws IOException {
try (FileWriter fileWriter = new FileWriter(realmFileCopy);
PrintWriter printWriter = new PrintWriter(fileWriter);) {
for (Map.Entry<String,Section> entry : sections.entrySet()) {
writeSection(printWriter, entry.getKey(), entry.getValue());
}
}
}
private static void writeSection(PrintWriter printWriter, String key, Section section) {
printWriter.printf("[%s \"%s\"]\n", section.getName(), section.getSubSection());
for (Entry entry : section.getEntries().values()) {
writeEntry(printWriter, entry.getKey(), entry.getValue());
}
}
private static void writeEntry(PrintWriter printWriter, String key, String value) {
printWriter.printf("\t%s = %s\n", key, escape(value));
}
private static String escape(String value) {
String fixedValue = '#' == value.charAt(0) ? "\"" + value + "\"" : value;
fixedValue = fixedValue.replace("\\", "\\\\");
return fixedValue;
}
private static String generateKey(String key, String subKey) {
return "k:" + key + "s:" + subKey;
}
private static class Section {
private final String name;
private final String subSection;
private final SortedMap<String, Entry> entries = new TreeMap<>();
public Section(String name, String subSection) {
this.name = name;
this.subSection = subSection;
}
public void addEntry(final String key, final String value) {
entries.put(generateKey(key, value), new Entry(key, value));
}
public String getName() {
return name;
}
public String getSubSection() {
return subSection;
}
public SortedMap<String, Entry> getEntries() {
return entries;
}
@Override
public int hashCode() {
return Objects.hash(name, subSection);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Section other = (Section) obj;
return Objects.equals(name, other.name) && Objects.equals(subSection, other.subSection);
}
@Override
public String toString() {
return String.format("Section [name=%s, subSection=%s]", name, subSection);
}
}
private static class Entry {
private final String key;
private final String value;
public Entry(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
@Override
public int hashCode() {
return Objects.hash(key, value);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Entry other = (Entry) obj;
return Objects.equals(key, other.key) && Objects.equals(value, other.value);
}
@Override
public String toString() {
return String.format("Entry [key=%s, value=%s]", key, value);
}
}
}
package com.gitblit.utils;
import org.slf4j.Logger;
import java.io.File;
/**
* The ContainerDetector tries to detect if the Gitblit instance
* is running in a container, or directly on the (virtualized) OS.
*/
public class ContainerDetector
{
private static Boolean inContainer;
private static String detectedType = "";
/**
* Detect if this instance in running inside a container.
*
* @return true - if a container could be detected
* false - otherwise
*/
public static boolean detect()
{
if (inContainer == null) {
File proc = new File("/proc/1/cgroup");
if (! proc.exists()) inContainer = Boolean.FALSE;
else {
String cgroups = FileUtils.readContent(proc, null);
if (cgroups.contains("/docker")) {
inContainer = Boolean.TRUE;
detectedType = "Docker container";
}
else if (cgroups.contains("/ecs")) {
inContainer = Boolean.TRUE;
detectedType = "ECS container";
}
else if (cgroups.contains("/kubepod") || cgroups.contains("/kubepods")) {
inContainer = Boolean.TRUE;
detectedType = "Kubernetes pod";
}
}
// Finally, if we still haven't found proof, it is probably not a container
if (inContainer == null) inContainer = Boolean.FALSE;
}
return inContainer;
}
/**
* Report to some output if a container was detected.
*
*/
public static void report(Logger logger, boolean onlyIfInContainer)
{
if (detect()) {
String msg = "Running in a " + detectedType;
if (logger == null) {
System.out.println(msg);
}
else logger.info(msg);
}
else if (!onlyIfInContainer) {
String msg = "Not detected to be running in a container";
if (logger == null) {
System.out.println(msg);
}
else logger.info(msg);
}
}
}

Sorry, the diff of this file is too big to display

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"
xml:lang="en"
lang="en">
<body>
<wicket:extend>
<div class="container">
<div class="markdown">
<div class="row">
<div class="span10 offset1">
<h3><center>空のリポジトリ</center></h3>
<div class="alert alert-info">
<span wicket:id="repository" style="font-weight: bold;">[repository]</span> は空のリポジトリです。表示するものはありません。
<p></p>
下記の URL にプッシュしてください。 <span wicket:id="pushurl"></span>
<hr/>
プッシュ完了後、このリポジトリページを<b>再読み込み</b>してください。
</div>
<h3><center>新規リポジトリの作成コマンド</center></h3>
<pre wicket:id="createSyntax"></pre>
<h3><center>既存リポジトリのプッシュコマンド</center></h3>
<pre wicket:id="existingSyntax"></pre>
<div class="span8 offset1">
<h2><center>Git の学習</center></h2>
<p>ここで紹介した情報に不案内でしたら、<a href="http://book.git-scm.com">Git Community Book</a> で Git の使い方をより理解してみませんか?</p>
<h4>ソース公開版 Git クライアント</h4>
<table>
<tbody>
<tr><td><a href="http://git-scm.com">Git</a></td><td>本家コマンドライン版 Git</td></tr>
<tr><td><a href="http://tortoisegit.googlecode.com">TortoiseGit</a></td><td>Windows エクスプローラ統合型 GUI (要 本家コマンドライン版 Git)</td></tr>
<tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a></td><td>エクリプス IDE 向け Git (Gitblit に似た JGit 使用 )</td></tr>
<tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a></td><td>Windows エクスプローラとVisual Studio に統合された、Git の C# 製 UI</td></tr>
<tr><td><a href="http://rowanj.github.io/gitx/">GitX-dev</a></td><td>Mac OS X 向け Git クライアント</td></tr>
</tbody>
</table>
<h4>商用/非ソース公開 Git クライアント</h4>
<table>
<tbody>
<tr><td><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a></td><td>Windows, Mac, Linux 向け、Java製 Git &amp; Mercurial クライアント</td></tr>
<tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a></td><td>フリーの Windows, Mac 向け Git &amp; Mercurial クライアント</td></tr>
<tr><td><a href="http://www.git-tower.com/">Tower</a></td><td>Mac OS X 向け Git クライアント</td></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</wicket:extend>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"
xml:lang="ru"
lang="ru">
<body>
<wicket:extend>
<div class="container">
<div class="markdown">
<div class="row">
<div class="span10 offset1">
<h3><center>Пустой репозиторий</center></h3>
<div class="alert alert-info">
<span wicket:id="repository" style="font-weight: bold;">[repository]</span> является пустым хранилищем и не может быть просмотрен Gitblit.
<p></p>
Пожалуйста, отправьте (push) некоторые коммиты <span wicket:id="pushurl"></span>
<hr/>
После того, как вы отправили коммиты, вы можете обновить эту страницу, чтобы просмотреть свой репозиторий.
</div>
<h3><center>Создать новый репозиторий в командной строке</center></h3>
<pre wicket:id="createSyntax"></pre>
<h3><center>Отправить существующий репозиторий из командной строки</center></h3>
<pre wicket:id="existingSyntax"></pre>
<div class="span8 offset1">
<h2><center>Учиться Git</center></h2>
<p>Если вы не знаете, как использовать эту информацию, рассмотрите <a href="http://book.git-scm.com">Git Community Book</a> чтобы лучше понять, как использовать Git.</p>
<h4>Git-клиенты с открытым исходным кодом</h4>
<table>
<tbody>
<tr><td><a href="http://git-scm.com">Git</a></td><td>the official, command-line Git</td></tr>
<tr><td><a href="http://tortoisegit.googlecode.com">TortoiseGit</a></td><td>Windows file explorer integration (requires official, command-line Git)</td></tr>
<tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a></td><td>Git for the Eclipse IDE (based on JGit, like Gitblit)</td></tr>
<tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a></td><td>C# frontend for Git that features Windows Explorer and Visual Studio integration</td></tr>
<tr><td><a href="http://rowanj.github.io/gitx/">GitX-dev</a></td><td>a Mac OS X Git client</td></tr>
</tbody>
</table>
<h4>Commercial/Closed-Source Git Clients</h4>
<table>
<tbody>
<tr><td><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a></td><td>A Java Git and Mercurial client for Windows, Mac, and Linux</td></tr>
<tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a></td><td>A free Git and Mercurial client for Windows & Mac</td></tr>
<tr><td><a href="http://www.git-tower.com/">Tower</a></td><td>a Mac OS X Git client</td></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</wicket:extend>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"
xml:lang="en"
lang="en">
<body>
<wicket:extend>
<div class="container">
<div class="markdown">
<div class="row">
<div class="span10 offset1">
<div class="alert alert-danger">
<h3><center>ファイルストアの使用方法</center></h3>
<p>
<strong>ファイルストアを使う場合、先ずは <a href="https://git-lfs.github.com/">Git-LFS Client</a> をインストールし、<code>git lfs install</code></strong> を実行しておかなければなりません。<br/>
<p>
その際、パスワード認証を使うのであれば、<a href="https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage">git credential storage</a> を設定するのがお勧めです。
Git-LFS が各ファイルに対してパスワードを要求するのを避けることが出来ます。<br/>
Windows での例: <code>git config --global credential.helper wincred</code>
</p>
</p>
</div>
<h3>クローン</h3>
<p>
既定の Git-LFS に繋いで <code>{repository}/info/lfs/objects/</code> を参照するには、単に <code>git clone</code> とするだけです。それ以上の操作は必要ありません。<br/>
<i>リポジトリがサードパーティの Git-LFS サーバーを使っている場合、<a href="https://github.com/github/git-lfs/blob/master/docs/spec.md#the-server"> 手動での設定する必要が有ります。</a></i>
</p>
<h3>追加</h3>
<p><code>git lfs track "*.bin"</code> を使ってファイルタイプやパスの設定を行った後ならば、単に <code>git add</code> コマンドでファイルの追加が行えます。<br/>
<i>追跡されたファイルもまた、<code>.gitattributes</code> ファイルを使うことで手動で設定できます。</i></p>
<h3>削除</h3>
<p>Git-LFS からファイルを削除した際には、リンクファイルがリポジトリから削除されるだけです。<br/>
<i>全てのファイルは、以前のバージョンとしてチェックアウト出来るよう、サーバーに残っています。</i>
</p>
<h3>詳細は...</h3>
<p><a href="https://github.com/github/git-lfs/blob/master/docs/spec.md">より詳しい最新の Git-LFS の仕様</a>を参照してください。</p>
<br />
</div>
</div>
</div>
</div>
</wicket:extend>
</body>
</html>

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

package com.gitblit.servlet;
import com.gitblit.Constants;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.tests.mock.MockGitblitContext;
import com.gitblit.tests.mock.MockRuntimeManager;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
public class RawServletTest
{
private static final char FSC = RawServlet.FSC;
private static MockRuntimeManager mockRuntimeManager = new MockRuntimeManager();
private static IStoredSettings settings;
private IRepositoryManager repositoryMngr;
private RawServlet rawServlet;
@BeforeClass
public static void init()
{
MockGitblitContext gitblitContext = new MockGitblitContext();
gitblitContext.addManager(mockRuntimeManager);
settings = mockRuntimeManager.getSettings();
}
@Before
public void setUp()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "/");
repositoryMngr = mock(IRepositoryManager.class);
rawServlet = new RawServlet(mockRuntimeManager, repositoryMngr);
}
@Test
public void asLink_HttpUrlRepo()
{
String baseUrl = "http://localhost";
String repository = "test.git";
String branch = null;
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/", link);
}
@Test
public void asLink_HttpUrlTrailingSlashRepo()
{
String baseUrl = "http://localhost/";
String repository = "test.git";
String branch = null;
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl.substring(0, baseUrl.length()-1) + Constants.RAW_PATH + repository + "/", link);
}
@Test
public void asLink_HttpUrlRepoLeadingSlash()
{
String baseUrl = "http://localhost";
String repository = "/test.git";
String branch = null;
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository.substring(1) + "/", link);
}
@Test
public void asLink_HttpUrlTrailingSlashRepoLeadingSlash()
{
String baseUrl = "http://localhost/";
String repository = "/test.git";
String branch = null;
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl.substring(0, baseUrl.length()-1) + Constants.RAW_PATH + repository.substring(1) + "/", link);
}
@Test
public void asLink_HttpUrlRepoBranch()
{
String baseUrl = "http://localhost";
String repository = "test.git";
String branch = "b52";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/" + branch + "/", link);
}
@Test
public void asLink_HttpUrlTrailingSlashRepoBranch()
{
String baseUrl = "http://localhost/";
String repository = "test.git";
String branch = "branch";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl.substring(0, baseUrl.length()-1) + Constants.RAW_PATH + repository + "/" + branch + "/", link);
}
@Test
public void asLink_HttpUrlRepoLeadingSlashBranch()
{
String baseUrl = "http://localhost";
String repository = "/test.git";
String branch = "featureOne";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository.substring(1) + "/" + branch + "/", link);
}
@Test
public void asLink_HttpUrlTrailingSlashRepoLeadingSlashBranch()
{
String baseUrl = "http://localhost/";
String repository = "/test.git";
String branch = "b";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl.substring(0, baseUrl.length()-1) + Constants.RAW_PATH + repository.substring(1) + "/" + branch + "/", link);
}
@Test
public void asLink_HttpUrlRepoBranchWithSlash()
{
String baseUrl = "http://localhost";
String repository = "test.git";
String branch = "feature/whatever";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/" + branch.replace('/', FSC) + "/", link);
}
@Test
public void asLink_HttpUrlTrailingSlashRepoBranchWithSlash()
{
String baseUrl = "http://localhost/";
String repository = "test.git";
String branch = "branch/for/issue/16";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl.substring(0, baseUrl.length()-1) + Constants.RAW_PATH + repository + "/"
+ branch.replace('/', FSC) + "/", link);
}
@Test
public void asLink_HttpUrlRepoLeadingSlashBranchWithSlash()
{
String baseUrl = "http://localhost";
String repository = "/test.git";
String branch = "releases/1.2.3";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository.substring(1) + "/"
+ branch.replace('/', FSC) + "/", link);
}
@Test
public void asLink_HttpUrlTrailingSlashRepoLeadingSlashBranchWithSlash()
{
String baseUrl = "http://localhost/";
String repository = "/test.git";
String branch = "b/52";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl.substring(0, baseUrl.length()-1) + Constants.RAW_PATH + repository.substring(1) + "/"
+ branch.replace('/', FSC) + "/", link);
}
@Test
public void asLink_HttpUrlRepoBranchPathFile()
{
String baseUrl = "http://localhost";
String repository = "test.git";
String branch = "b52";
String path = "file.txt";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/" + branch + "/" + path, link);
}
@Test
public void asLink_HttpUrlTrailingSlashRepoBranchPathFolderFile()
{
String baseUrl = "http://localhost/";
String repository = "test.git";
String branch = "branch";
String path = "path/to/file.png";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl.substring(0, baseUrl.length()-1) + Constants.RAW_PATH + repository + "/"
+ branch + "/" + path.replace('/', FSC), link);
}
@Test
public void asLink_HttpUrlRepoLeadingSlashBranchPathFolderLeadingSlash()
{
String baseUrl = "http://localhost";
String repository = "/test.git";
String branch = "featureOne";
String path = "/folder";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository.substring(1) + "/" + branch + path, link);
}
@Test
public void asLink_HttpUrlTrailingSlashRepoLeadingSlashBranchSubFolder()
{
String baseUrl = "http://localhost/";
String repository = "/test.git";
String branch = "b";
String path = "sub/folder";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl.substring(0, baseUrl.length()-1) + Constants.RAW_PATH + repository.substring(1) + "/"
+ branch + "/" + path.replace('/', FSC), link);
}
@Test
public void asLink_HttpUrlRepoBranchWithSlashPathFolder()
{
String baseUrl = "http://localhost";
String repository = "test.git";
String branch = "feature/whatever";
String path = "folder";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch.replace('/', FSC) + "/" + path, link);
}
@Test
public void asLink_HttpUrlTrailingSlashRepoBranchWithSlashPathFolderFile()
{
String baseUrl = "http://localhost/";
String repository = "test.git";
String branch = "branch/for/issue/16";
String path = "a/file.gif";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl.substring(0, baseUrl.length()-1) + Constants.RAW_PATH + repository + "/"
+ branch.replace('/', FSC) + "/" + path.replace('/', FSC), link);
}
@Test
public void asLink_HttpUrlRepoLeadingSlashBranchWithSlashPathFile()
{
String baseUrl = "http://localhost";
String repository = "/test.git";
String branch = "releases/1.2.3";
String path = "hurray.png";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository.substring(1) + "/"
+ branch.replace('/', FSC) + "/" + path, link);
}
@Test
public void asLink_HttpUrlTrailingSlashRepoLeadingSlashBranchWithSlashPathFolderFile()
{
String baseUrl = "http://localhost/";
String repository = "/test.git";
String branch = "b/52";
String path = "go/to/f.k";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl.substring(0, baseUrl.length()-1) + Constants.RAW_PATH + repository.substring(1) + "/"
+ branch.replace('/', FSC) + "/" + path.replace('/', FSC), link);
}
@Test
public void asLink_HttpUrlRepoInFolder()
{
String baseUrl = "http://localhost";
String repository = "project/repo.git";
String branch = null;
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/", link);
}
@Test
public void asLink_HttpUrlRepoInSubFolder()
{
String baseUrl = "http://localhost";
String repository = "some/project/repo.git";
String branch = null;
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/", link);
}
@Test
public void asLink_HttpUrlRepoInSubFolderBranch()
{
String baseUrl = "http://localhost";
String repository = "some/project/repo.git";
String branch = "laluna";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch + "/", link);
}
@Test
public void asLink_HttpUrlRepoInSubFolderBranchWithSlash()
{
String baseUrl = "http://localhost";
String repository = "some/project/repo.git";
String branch = "la/le/lu";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch.replace('/', FSC) + "/", link);
}
@Test
public void asLink_HttpUrlRepoInSubFolderBranchPathFile()
{
String baseUrl = "http://localhost";
String repository = "some/project/repo.git";
String branch = "laluna";
String path = "elrtkx.fg";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch + "/" + path, link);
}
@Test
public void asLink_HttpUrlRepoInSubFolderLeadingSlashBranchWithSlashPathFolderFile()
{
String baseUrl = "http://localhost";
String repository = "/some/project/repo.git";
String branch = "la/le/lu";
String path = "doremi/fa/SOLA/di.mp3";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository.substring(1) + "/"
+ branch.replace('/', FSC) + "/" + path.replace('/', FSC), link);
}
@Test
public void asLink_HttpUrlRepoPathFolderFile()
{
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = null;
String path = "doko/di.mp3";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/", link);
}
@Test
public void asLink_HttpUrlRepoTrailingSlashPathFileLeadingSlash()
{
String baseUrl = "http://localhost";
String repository = "repo.git/";
String branch = null;
String path = "/di.mp3";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository, link);
}
@Test
public void asLink_HttpUrlRepoBranchPathFileLeadingSlash()
{
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "bee";
String path = "/bop.mp3";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch + path, link);
}
@Test
public void asLink_HttpUrlRepoBranchPathFolderLeadingSlashTrailingSlash()
{
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "bee";
String path = "/bam/";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch + "/bam" + FSC, link);
}
@Test
public void asLink_HttpUrlRepoBranchPathSubFolderLeadingSlashTrailingSlash()
{
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "bee";
String path = "/bapedi/boo/";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch + "/" + "bapedi" + FSC + "boo" + FSC, link);
}
@Test
public void asLink_HttpUrlRepoCommitId()
{
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "c7eef37bfe5ae246cdf5ca5c502e4b5471290cb1";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch + "/", link);
}
@Test
public void asLink_HttpUrlRepoCommitIdPathFile()
{
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "c7eef37bfe5ae246cdf5ca5c502e4b5471290cb1";
String path = "file";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch + "/" + path, link);
}
@Test
public void asLink_HttpUrlRepoCommitIdPathFolderFileFile()
{
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "c7eef37bfe5ae246cdf5ca5c502e4b5471290cb1";
String path = "file/in/folder";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch + "/" + path.replace('/', FSC), link);
}
@Test
public void asLink_HttpUrlRepoBranchWithSlash_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "|");
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "some/feature";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch.replaceAll("/", "|") + "/", link);
}
@Test
public void asLink_HttpUrlRepoBranchWithSlashPathFolderFile_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ";");
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "some/feature";
String path = "file/in/folder";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch.replaceAll("/", ";") + "/" + path.replaceAll("/", ";"), link);
}
@Test
public void asLink_HttpUrlRepoBranchWithSlash_explicitFscSameAsDefault()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "!");
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "some/feature";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch.replaceAll("/", "!") + "/", link);
}
@Test
public void asLink_HttpUrlRepoBranchWithSlashPathFolderFile_explicitFscSameAsDefault()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "!");
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "some/feature";
String path = "file/in/folder";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch.replaceAll("/", "!") + "/" + path.replaceAll("/", "!"), link);
}
@Test
public void asLink_HttpUrlRepoBranchWithDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ":");
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "important" + FSC + "feature";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch + "/", link);
}
@Test
public void asLink_HttpUrlRepoBranchWithSlashPathFileWithDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "|");
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "some/feature";
String path = "large" + FSC + "file";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch.replaceAll("/", "|") + "/" + path, link);
}
@Test
public void asLink_HttpUrlRepoBranchWithDefaultFscAndSlash_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ":");
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "hotf" + FSC + "x/issue/1234";
String path = null;
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch.replaceAll("/", ":") + "/", link);
}
@Test
public void asLink_HttpUrlRepoBranchWithDefaultFscAndSlashPathFolderFileWithDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "|");
String baseUrl = "http://localhost";
String repository = "repo.git";
String branch = "some/feature" + FSC + "in/here";
String path = "large" + FSC + "stuff/folder/file" + FSC + "16";
String link = RawServlet.asLink(baseUrl, repository, branch, path);
assertNotNull(link);
assertEquals(baseUrl + Constants.RAW_PATH + repository + "/"
+ branch.replaceAll("/", "|") + "/" + path.replaceAll("/", "|"), link);
}
@Test
public void getBranch_Repo()
{
String branch = rawServlet.getBranch("test.git", "test.git/");
assertEquals("Branch was supposed to be empty as no branch was given.", "", branch);
}
@Test
public void getBranch_PiNull()
{
String branch = rawServlet.getBranch("test.git", null);
assertEquals("Branch was supposed to be empty as path info is null.", "", branch);
}
@Test
public void getBranch_PiEmpty()
{
String branch = rawServlet.getBranch("test.git", "");
assertEquals("Branch was supposed to be empty as no path info exists.", "", branch);
}
@Test
public void getBranch_LeadinRepo()
{
String branch = rawServlet.getBranch("test.git", "some/test.git/");
assertEquals("Branch was supposed to be empty as no branch was given.", "", branch);
}
@Test
public void getBranch_ProjectRepo()
{
String branch = rawServlet.getBranch("smack/dab.git", "smack/dab.git/");
assertEquals("Branch was supposed to be empty as no branch was given.", "", branch);
}
@Test
public void getBranch_RepoBranch()
{
String branch = rawServlet.getBranch("test.git", "test.git/bee");
assertEquals("bee", branch);
}
@Test
public void getBranch_LeadinRepoBranch()
{
String branch = rawServlet.getBranch("repo.git", "project/repo.git/bae");
assertEquals("bae", branch);
}
@Test
public void getBranch_ProjectRepoBranch()
{
String branch = rawServlet.getBranch("test/r.git", "test/r.git/b");
assertEquals("b", branch);
}
@Test
public void getBranch_LeadinProjectRepoBranch()
{
String branch = rawServlet.getBranch("test/r.git", "a/b/test/r.git/b");
assertEquals("b", branch);
}
@Test
public void getBranch_RepoBranchTrailingSlash()
{
String branch = rawServlet.getBranch("/test.git", "test.git/fixthis/");
assertEquals("fixthis", branch);
}
@Test
public void getBranch_RepoBranchFile()
{
String branch = rawServlet.getBranch("/bob.git", "bob.git/branch/file.txt");
assertEquals("branch", branch);
}
@Test
public void getBranch_RepoBranchFolderFile()
{
String branch = rawServlet.getBranch("/bill.git", "bill.git/flex/fold!laundr.y");
assertEquals("flex", branch);
}
@Test
public void getBranch_RepoBranchFoldersTrailingSlash()
{
String branch = rawServlet.getBranch("bill.git", "bill.git/flex/fold!gold/");
assertEquals("flex", branch);
}
@Test
public void getBranch_RepoBranchFoldersTrailingFsc()
{
String branch = rawServlet.getBranch("bill.git", "bill.git/flex/fold"+ FSC + "gold" + FSC);
assertEquals("flex", branch);
}
@Test
public void getBranch_LeadinProjectRepoBranchFoldersTrailingSlash()
{
String branch = rawServlet.getBranch("bam/bum.git", "bim/bam/bum.git/klingeling/dumm" + FSC + "di" + FSC + "dumm/");
assertEquals("klingeling", branch);
}
@Test
public void getBranch_LeadinProjectRepoBranchFoldersTrailingFsc()
{
String branch = rawServlet.getBranch("bam/bum.git", "bim/bam/bum.git/klingeling/dumm" + FSC + "di" + FSC + "dumm" + FSC);
assertEquals("klingeling", branch);
}
@Test
public void getBranch_RepoCommitid()
{
String branch = rawServlet.getBranch("git.git", "git.git/a02159e6378d63d0e1ad3c04a05462d9fc62fe89");
assertEquals("a02159e6378d63d0e1ad3c04a05462d9fc62fe89", branch);
}
@Test
public void getBranch_ProjectRepoCommitidFolderTrailingSlash()
{
String branch = rawServlet.getBranch("git/git.git", "git/git.git/a02159e6378d63d0e1ad3c04a05462d9fc62fe89/src/");
assertEquals("a02159e6378d63d0e1ad3c04a05462d9fc62fe89", branch);
}
@Test
public void getBranch_ProjectRepoCommitidFolderTrailingFsc()
{
String branch = rawServlet.getBranch("git/git.git", "git/git.git/a02159e6378d63d0e1ad3c04a05462d9fc62fe89/src" + FSC);
assertEquals("a02159e6378d63d0e1ad3c04a05462d9fc62fe89", branch);
}
@Test
public void getBranch_ProjectSubRepoCommitidFolderFile()
{
String branch = rawServlet.getBranch("git/git.git", "Git implementations/git/git.git/a02159e6378d63d0e1ad3c04a05462d9fc62fe89/src" + FSC + "README.md");
assertEquals("a02159e6378d63d0e1ad3c04a05462d9fc62fe89", branch);
}
@Test
public void getBranch_RepoBranchWithFsc()
{
String branch = rawServlet.getBranch("git.git", "git.git/feature" + FSC + "rebase");
assertEquals("feature/rebase", branch);
}
@Test
public void getBranch_RepoBranchWithTwoFsc()
{
String branch = rawServlet.getBranch("git.git", "git.git/feature" + FSC + "rebase" + FSC + "onto");
assertEquals("feature/rebase/onto", branch);
}
@Test
public void getBranch_ProjectRepoBranchWithTwoFsc()
{
String branch = rawServlet.getBranch("Java/git/git.git", "Java/git/git.git/feature" + FSC + "rebase" + FSC + "onto");
assertEquals("feature/rebase/onto", branch);
}
@Test
public void getBranch_RepoBranchWithTwoFscTrailingSlash()
{
String branch = rawServlet.getBranch("git.git", "git.git/feature" + FSC + "rebase" + FSC + "onto/");
assertEquals("feature/rebase/onto", branch);
}
@Test
public void getBranch_ProjectRepoBranchWithTwoFscTrailingSlash()
{
String branch = rawServlet.getBranch("in Go/git.git", "in Go/git.git/feature" + FSC + "rebase" + FSC + "onto/");
assertEquals("feature/rebase/onto", branch);
}
@Test
public void getBranch_LeadinProjectRepoBranchWithTwoFscTrailingSlash()
{
String branch = rawServlet.getBranch("Go/git.git", "all the gits/Go/git.git/feature" + FSC + "rebase" + FSC + "onto/");
assertEquals("feature/rebase/onto", branch);
}
@Test
public void getBranch_RepoBranchWithFscFolder()
{
String branch = rawServlet.getBranch("git.git", "git.git/feature" + FSC + "rebase/onto");
assertEquals("feature/rebase", branch);
}
@Test
public void getBranch_RepoBranchWithFscFolderFile()
{
String branch = rawServlet.getBranch("git.git", "git.git/feature" + FSC + "rebase/onto" + FSC + "head");
assertEquals("feature/rebase", branch);
}
@Test
public void getBranch_RepoBranchWithFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "|");
String branch = rawServlet.getBranch("git.git", "git.git/some|feature");
assertEquals("some/feature", branch);
}
@Test
public void getBranch_RepoBranchWithFsc_explicitFscSameAsDefault()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, FSC);
String branch = rawServlet.getBranch("git.git", "git.git/some" + FSC + "feature");
assertEquals("some/feature", branch);
}
@Test
public void getBranch_RepoBranchWithFscFolders_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ":");
String branch = rawServlet.getBranch("git.git", "git.git/hotfix:1.2.3/src:main:java/");
assertEquals("hotfix/1.2.3", branch);
}
@Test
public void getBranch_LeadindRepoBranchWithFscFolderFile_explicitFscSameAsDefault()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, FSC);
String branch = rawServlet.getBranch("git.git", "IBM/git.git/some" + FSC + "feature/some" + FSC + "folder" + FSC + "file.dot");
assertEquals("some/feature", branch);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getBranch_RepoBranchWithDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ";");
String branch = rawServlet.getBranch("git.git", "git.git/some" + FSC + "feature");
assertEquals("some" + FSC + "feature", branch);
}
@Test
public void getBranch_RepoBranchWithDifferentFscFolderFileWithDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ";");
String branch = rawServlet.getBranch("git.git", "git.git/some;feature/path" + FSC + "to" + FSC + "file.txt");
assertEquals("some/feature", branch);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getBranch_RepoBranchWithDefaultFscAndDifferentFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ":");
String branch = rawServlet.getBranch("git.git", "git.git/go" + FSC + "to:start");
assertEquals("go" + FSC + "to/start", branch);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getBranch_RepoBranchWithDefaultFscAndDifferentFscFolderWithDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String branch = rawServlet.getBranch("git.git", "git.git/go" + FSC + "to+prison/dont" + FSC + "collect");
assertEquals("go" + FSC + "to/prison", branch);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getBranch_RepoBranchWithDefaultFscAndDifferentFscFolderWithDefaultFscTrailingSlash_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String branch = rawServlet.getBranch("git.git", "git.git/go" + FSC + "to+ prison/dont" + FSC + "collect/");
assertEquals("go" + FSC + "to/prison", branch);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getBranch_RepoBranchWithDefaultFscAndDifferentFscFolderWithDefaultFscTrailingFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String branch = rawServlet.getBranch("git.git", "git.git/go" + FSC + "to+prison/dont" + FSC + "collect+");
assertEquals("go" + FSC + "to/prison", branch);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getBranch_RepoBranchWithDefaultFscAndDifferentFscFolderWithDefaultFscTrailingDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String branch = rawServlet.getBranch("git.git", "git.git/go" + FSC + "to+prison/dont" + FSC + "collect" + FSC);
assertEquals("go" + FSC + "to/prison", branch);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getBranch_RepoBranchWithDefaultFscAndDifferentFscFolderFileWithDefaultFscAndDifferentFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String branch = rawServlet.getBranch("git.git", "git.git/go" + FSC + "to+prison/dont" + FSC + "collect+money.eur");
assertEquals("go" + FSC + "to/prison", branch);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getBranch_LeadinProjectRepoBranchWithDefaultFscAndDifferentFscFolderFileWithDefaultFscAndDifferentFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String branch = rawServlet.getBranch("games/Monopoly/git.git", "blah/games/Monopoly/git.git/go" + FSC + "to+prison/dont" + FSC + "collect+money.eur");
assertEquals("go" + FSC + "to/prison", branch);
}
@Test
public void getPath_Repo()
{
String path = rawServlet.getPath("test.git", "", "test.git/");
assertEquals("Path was supposed to be empty as no path was given.", "", path);
}
@Test
public void getPath_PiNull()
{
String path = rawServlet.getPath("test.git", "", null);
assertEquals("Path was supposed to be empty as path info is null.", "", path);
}
@Test
public void getPath_PiEmpty()
{
String path = rawServlet.getPath("test.git", "", "");
assertEquals("Path was supposed to be empty as no path info exists.", "", path);
}
@Test
public void getPath_LeadinRepo()
{
String path = rawServlet.getPath("test.git", "", "some/test.git/");
assertEquals("Path was supposed to be empty as no path was given.", "", path);
}
@Test
public void getPath_ProjectRepo()
{
String path = rawServlet.getPath("smack/dab.git", "", "smack/dab.git/");
assertEquals("Path was supposed to be empty as no path was given.", "", path);
}
@Test
public void getPath_RepoBranch()
{
String path = rawServlet.getPath("test.git", "bee", "test.git/bee");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_LeadinRepoBranch()
{
String path = rawServlet.getPath("repo.git", "bae", "project/repo.git/bae");
assertEquals("Expected path to be empty since no path was present","" , path);
}
@Test
public void getPath_ProjectRepoBranch()
{
String path = rawServlet.getPath("test/r.git", "b", "test/r.git/b");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_LeadinProjectRepoBranch()
{
String path = rawServlet.getPath("test/r.git", "b", "a/b/test/r.git/b");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_RepoBranchTrailingSlash()
{
String path = rawServlet.getPath("test.git", "fixthis", "test.git/fixthis/");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_RepoBranchFile()
{
String path = rawServlet.getPath("/bob.git", "branch", "bob.git/branch/file.txt");
assertEquals("file.txt", path);
}
@Test
public void getPath_RepoBranchFolderFile()
{
String path = rawServlet.getPath("/bill.git", "flex", "bill.git/flex/fold" + FSC + "laundr.y");
assertEquals("fold/laundr.y", path);
}
@Test
public void getPath_RepoBranchFoldersTrailingSlash()
{
String path = rawServlet.getPath("bill.git", "flex", "bill.git/flex/fold"+ FSC + "gold/");
assertEquals("fold/gold", path);
}
@Test
public void getPath_RepoBranchFoldersTrailingFsc()
{
String path = rawServlet.getPath("bill.git", "flex", "bill.git/flex/fold"+ FSC + "gold" + FSC);
assertEquals("fold/gold", path);
}
@Test
public void getPath_LeadinProjectRepoBranchFoldersTrailingSlash()
{
String path = rawServlet.getPath("bam/bum.git", "klingeling", "bim/bam/bum.git/klingeling/dumm" + FSC + "di" + FSC + "dumm/");
assertEquals("dumm/di/dumm", path);
}
@Test
public void getPath_LeadinProjectRepoBranchFoldersTrailingFsc()
{
String path = rawServlet.getPath("bam/bum.git", "klingeling", "bim/bam/bum.git/klingeling/dumm" + FSC + "di" + FSC + "dumm" + FSC);
assertEquals("dumm/di/dumm", path);
}
@Test
public void getPath_RepoCommitid()
{
String path = rawServlet.getPath("/git.git", "a02159e6378d63d0e1ad3c04a05462d9fc62fe89", "git.git/a02159e6378d63d0e1ad3c04a05462d9fc62fe89/");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_RepoCommitidNoTrailingSlash()
{
String path = rawServlet.getPath("/git.git", "a02159e6378d63d0e1ad3c04a05462d9fc62fe89", "git.git/a02159e6378d63d0e1ad3c04a05462d9fc62fe89");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_ProjectRepoCommitidFolderTrailingSlash()
{
String path = rawServlet.getPath("git/git.git", "a02159e6378d63d0e1ad3c04a05462d9fc62fe89", "git/git.git/a02159e6378d63d0e1ad3c04a05462d9fc62fe89/src/");
assertEquals("src", path);
}
@Test
public void getPath_ProjectRepoCommitidFolderTrailingFsc()
{
String path = rawServlet.getPath("git/git.git", "a02159e6378d63d0e1ad3c04a05462d9fc62fe89", "git/git.git/a02159e6378d63d0e1ad3c04a05462d9fc62fe89/src" + FSC);
assertEquals("src", path);
}
@Test
public void getPath_ProjectSubRepoCommitidFolderFile()
{
String path = rawServlet.getPath("git/git.git", "a02159e6378d63d0e1ad3c04a05462d9fc62fe89", "Git implementations/git/git.git/a02159e6378d63d0e1ad3c04a05462d9fc62fe89/src" + FSC + "README.md");
assertEquals("src/README.md", path);
}
@Test
public void getPath_RepoBranchWithFsc()
{
String path = rawServlet.getPath("git.git", "feature/rebase", "git.git/feature" + FSC + "rebase");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_RepoBranchWithTwoFsc()
{
String path = rawServlet.getPath("git.git", "feature/rebase/onto", "git.git/feature" + FSC + "rebase" + FSC + "onto");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_ProjectRepoBranchWithTwoFsc()
{
String path = rawServlet.getPath("Java/git/git.git", "feature/rebase/onto", "Java/git/git.git/feature" + FSC + "rebase" + FSC + "onto");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_RepoBranchWithTwoFscTrailingSlash()
{
String path = rawServlet.getPath("git.git", "feature/rebase/onto", "git.git/feature" + FSC + "rebase" + FSC + "onto/");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_ProjectRepoBranchWithTwoFscTrailingSlash()
{
String path = rawServlet.getPath("in Go/git.git", "feature/rebase/onto", "in Go/git.git/feature" + FSC + "rebase" + FSC + "onto/");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_LeadinProjectRepoBranchWithTwoFscTrailingSlash()
{
String path = rawServlet.getPath("Go/git.git", "feature/rebase/onto", "all the gits/Go/git.git/feature" + FSC + "rebase" + FSC + "onto/");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_RepoBranchWithFscFolder()
{
String path = rawServlet.getPath("git.git", "feature/rebase", "git.git/feature" + FSC + "rebase/onto");
assertEquals("onto", path);
}
@Test
public void getPath_RepoBranchWithFscFolderFile()
{
String path = rawServlet.getPath("git.git", "feature/rebase", "git.git/feature" + FSC + "rebase/onto" + FSC + "head");
assertEquals("onto/head", path);
}
@Test
public void getPath_RepoBranchWithFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "|");
String path = rawServlet.getPath("git.git", "some/feature", "git.git/some|feature");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_RepoBranchWithFsc_explicitFscSameAsDefault()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, String.valueOf(FSC));
String path = rawServlet.getPath("git.git", "some/feature", "git.git/some" + FSC + "feature");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_RepoBranchWithFscFoldersTrailingSlash_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ":");
String path = rawServlet.getPath("git.git", "hotfix/1.2.3", "git.git/hotfix:1.2.3/src:main:java/");
assertEquals("src/main/java", path);
}
@Test
public void getPath_LeadindRepoBranchWithFscFolderFile_explicitFscSameAsDefault()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, String.valueOf(FSC));
String path = rawServlet.getPath("git.git", "some/feature", "IBM/git.git/some" + FSC + "feature/some" + FSC + "folder" + FSC + "file.dot");
assertEquals("some/folder/file.dot", path);
}
@Test
public void getPath_RepoBranchWithDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ";");
String path = rawServlet.getPath("git.git", "some" + FSC + "feature", "git.git/some" + FSC + "feature");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Test
public void getPath_RepoBranchWithDefaultFscTrailingSlash_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ";");
String path = rawServlet.getPath("git.git", "some" + FSC + "feature", "git.git/some" + FSC + "feature/");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getPath_RepoBranchWithDifferentFscFolderFileWithDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ";");
String path = rawServlet.getPath("git.git", "some/feature", "git.git/some;feature/path" + FSC + "to" + FSC + "file.txt");
assertEquals("path" + FSC + "to" + FSC + "file.txt", path);
}
@Test
public void getPath_RepoBranchWithDefaultFscAndDifferentFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, ":");
String path = rawServlet.getPath("git.git", "go" + FSC + "to/start", "git.git/go" + FSC + "to:start");
assertEquals("Expected returned path to be empty since no path was present", "", path);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getPath_RepoBranchWithDefaultFscAndDifferentFscFolderWithDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String path = rawServlet.getPath("git.git", "go" + FSC + "to/prison", "git.git/go" + FSC + "to+prison/dont" + FSC + "collect");
assertEquals("dont" + FSC + "collect", path);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getPath_RepoBranchWithDefaultFscAndDifferentFscFolderWithDefaultFscTrailingSlash_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String path = rawServlet.getPath("git.git", "go" + FSC + "to/prison", "git.git/go" + FSC + "to+prison/dont" + FSC + "collect/");
assertEquals("dont" + FSC + "collect", path);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getPath_RepoBranchWithDefaultFscAndDifferentFscFolderWithDefaultFscTrailingFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String path = rawServlet.getPath("git.git", "go" + FSC + "to/prison", "git.git/go" + FSC + "to+prison/dont" + FSC + "collect+");
assertEquals("dont" + FSC + "collect", path);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getPath_RepoBranchWithDefaultFscAndDifferentFscFolderWithDefaultFscTrailingDefaultFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String path = rawServlet.getPath("git.git", "go" + FSC + "to/prison", "git.git/go" + FSC + "to+prison/dont" + FSC + "collect" + FSC);
assertEquals("dont" + FSC + "collect" + FSC, path);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getPath_RepoBranchWithDefaultFscAndDifferentFscFolderFileWithDefaultFscAndDifferentFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String path = rawServlet.getPath("git.git", "go" + FSC + "to/prison", "git.git/go" + FSC + "to+prison/" + FSC + "dont" + FSC + "collect+money.eur");
assertEquals(FSC + "dont" + FSC + "collect/money.eur", path);
}
@Ignore // TODO: Why was it implemented this way?
@Test
public void getPath_LeadinProjectRepoBranchWithDefaultFscAndDifferentFscFolderFileWithDefaultFscAndDifferentFsc_differentFsc()
{
settings.overrideSetting(Keys.web.forwardSlashCharacter, "+");
String path = rawServlet.getPath("games/Monopoly/git.git", "go" + FSC + "to/prison", "blah/games/Monopoly/git.git/go" + FSC + "to+prison/dont" + FSC + "collect+money.eur");
assertEquals("dont" + FSC + "collect/money.eur", path);
}
}
package com.gitblit.tests.mock;
import com.gitblit.manager.IManager;
import com.gitblit.servlet.GitblitContext;
public class MockGitblitContext extends GitblitContext
{
public <X extends IManager> void addManager(X x)
{
startManager(x);
}
}
/*
* Copyright 2011 gitblit.com.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gitblit.utils;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import com.gitblit.tests.GitblitUnitTest;
import org.junit.Test;
public class TimeUtilsTest extends GitblitUnitTest
{
private Date offset(long subtract) {
return new Date(System.currentTimeMillis() - subtract);
}
private Date offset(long now, long subtract) {
return new Date(now - subtract);
}
@Test
public void testBasicTimeFunctions() throws Exception {
assertEquals(2, TimeUtils.minutesAgo(offset(2 * TimeUtils.MIN), false));
assertEquals(3, TimeUtils.minutesAgo(offset((2 * TimeUtils.MIN) + (35 * 1000L)), true));
assertEquals(2, TimeUtils.hoursAgo(offset(2 * TimeUtils.ONEHOUR), false));
assertEquals(3, TimeUtils.hoursAgo(offset(5 * TimeUtils.HALFHOUR), true));
assertEquals(4, TimeUtils.daysAgo(offset(4 * TimeUtils.ONEDAY)));
}
@Test
public void testToday() throws Exception {
assertTrue(TimeUtils.isToday(new Date(), null));
}
@Test
public void testYesterday() throws Exception {
assertTrue(TimeUtils.isYesterday(offset(TimeUtils.ONEDAY), null));
}
@Test
public void testDurations() throws Exception {
TimeUtils timeUtils = new TimeUtils();
assertEquals("1 day", timeUtils.duration(1));
assertEquals("5 days", timeUtils.duration(5));
assertEquals("3 months", timeUtils.duration(75));
assertEquals("12 months", timeUtils.duration(364));
assertEquals("1 year", timeUtils.duration(365 + 0));
assertEquals("1 year", timeUtils.duration(365 + 10));
assertEquals("1 year, 1 month", timeUtils.duration(365 + 15));
assertEquals("1 year, 1 month", timeUtils.duration(365 + 30));
assertEquals("1 year, 1 month", timeUtils.duration(365 + 44));
assertEquals("1 year, 2 months", timeUtils.duration(365 + 45));
assertEquals("1 year, 2 months", timeUtils.duration(365 + 60));
assertEquals("2 years", timeUtils.duration(2 * 365 + 0));
assertEquals("2 years", timeUtils.duration(2 * 365 + 10));
assertEquals("2 years, 1 month", timeUtils.duration(2 * 365 + 15));
assertEquals("2 years, 1 month", timeUtils.duration(2 * 365 + 30));
assertEquals("2 years, 1 month", timeUtils.duration(2 * 365 + 44));
assertEquals("2 years, 2 months", timeUtils.duration(2 * 365 + 45));
assertEquals("2 years, 2 months", timeUtils.duration(2 * 365 + 60));
}
@Test
public void testTimeAgo() throws Exception {
// standard time ago tests
TimeUtils timeUtils = new TimeUtils();
assertEquals("just now", timeUtils.timeAgo(offset(1 * TimeUtils.MIN)));
assertEquals("60 mins ago", timeUtils.timeAgo(offset(60 * TimeUtils.MIN)));
assertEquals("2 hours ago", timeUtils.timeAgo(offset(120 * TimeUtils.MIN)));
assertEquals("15 hours ago", timeUtils.timeAgo(offset(15 * TimeUtils.ONEHOUR)));
assertEquals("yesterday", timeUtils.timeAgo(offset(24 * TimeUtils.ONEHOUR)));
assertEquals("2 days ago", timeUtils.timeAgo(offset(2 * TimeUtils.ONEDAY)));
assertEquals("5 weeks ago", timeUtils.timeAgo(offset(35 * TimeUtils.ONEDAY)));
assertEquals("3 months ago", timeUtils.timeAgo(offset(84 * TimeUtils.ONEDAY)));
assertEquals("3 months ago", timeUtils.timeAgo(offset(95 * TimeUtils.ONEDAY)));
assertEquals("4 months ago", timeUtils.timeAgo(offset(104 * TimeUtils.ONEDAY)));
assertEquals("1 year ago", timeUtils.timeAgo(offset(365 * TimeUtils.ONEDAY)));
assertEquals("13 months ago", timeUtils.timeAgo(offset(395 * TimeUtils.ONEDAY)));
assertEquals("2 years ago", timeUtils.timeAgo(offset((2 * 365 + 30) * TimeUtils.ONEDAY)));
}
@Test
public void testTimeAgoCss() throws Exception {
// css class tests
TimeUtils timeUtils = new TimeUtils();
assertEquals("age0", timeUtils.timeAgoCss(offset(1 * TimeUtils.MIN)));
assertEquals("age0", timeUtils.timeAgoCss(offset(60 * TimeUtils.MIN)));
assertEquals("age1", timeUtils.timeAgoCss(offset(120 * TimeUtils.MIN)));
assertEquals("age1", timeUtils.timeAgoCss(offset(24 * TimeUtils.ONEHOUR)));
assertEquals("age2", timeUtils.timeAgoCss(offset(2 * TimeUtils.ONEDAY)));
}
@Test
public void testTimeAgoYesterday() throws Exception {
TimeZone myTimezone = TimeZone.getTimeZone("GMT");
TimeUtils timeUtils = new TimeUtils(null, myTimezone);
Calendar myCal = Calendar.getInstance(myTimezone);
myCal.set(Calendar.HOUR_OF_DAY, 12);
myCal.set(Calendar.MINUTE, 0);
long now = myCal.getTime().getTime();
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,23 * TimeUtils.ONEHOUR), false, now));
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (29 * TimeUtils.MIN)), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (31 * TimeUtils.MIN)), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,35 * TimeUtils.ONEHOUR), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,36 * TimeUtils.ONEHOUR), false, now));
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,37 * TimeUtils.ONEHOUR), false, now));
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,44 * TimeUtils.ONEHOUR), false, now));
}
@Test
public void testTimeAgoYesterdayCET() throws Exception {
TimeZone myTimezone = TimeZone.getTimeZone("CET");
TimeUtils timeUtils = new TimeUtils(null, myTimezone);
Calendar myCal = Calendar.getInstance(myTimezone);
myCal.set(Calendar.HOUR_OF_DAY, 22);
myCal.set(Calendar.MINUTE, 0);
long now = myCal.getTime().getTime();
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,23 * TimeUtils.ONEHOUR), false, now));
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (29 * TimeUtils.MIN)), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (31 * TimeUtils.MIN)), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,36 * TimeUtils.ONEHOUR), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,46 * TimeUtils.ONEHOUR), false, now));
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,47 * TimeUtils.ONEHOUR), false, now));
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,56 * TimeUtils.ONEHOUR), false, now));
}
@Test
public void testTimeAgoYesterdayPST() throws Exception {
TimeZone myTimezone = TimeZone.getTimeZone("PST");
TimeUtils timeUtils = new TimeUtils(null, myTimezone);
Calendar myCal = Calendar.getInstance(myTimezone);
myCal.set(Calendar.HOUR_OF_DAY, 8);
myCal.set(Calendar.MINUTE, 0);
long now = myCal.getTime().getTime();
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,23 * TimeUtils.ONEHOUR), false, now));
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (29 * TimeUtils.MIN)), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (31 * TimeUtils.MIN)), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,30 * TimeUtils.ONEHOUR), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,32 * TimeUtils.ONEHOUR), false, now));
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,33 * TimeUtils.ONEHOUR), false, now));
assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,48 * TimeUtils.ONEHOUR), false, now));
}
@Test
public void testFrequency() {
assertEquals(5, TimeUtils.convertFrequencyToMinutes("2 mins", 5));
assertEquals(10, TimeUtils.convertFrequencyToMinutes("10 mins", 5));
assertEquals(600, TimeUtils.convertFrequencyToMinutes("10 hours", 5));
assertEquals(14400, TimeUtils.convertFrequencyToMinutes(" 10 days ", 5));
}
@Test
public void testTimeAgoDaysAgo() throws Exception {
TimeZone myTimezone = TimeZone.getTimeZone("GMT");
TimeUtils timeUtils = new TimeUtils(null, myTimezone);
Calendar myCal = Calendar.getInstance(myTimezone);
myCal.set(Calendar.HOUR_OF_DAY, 12);
myCal.set(Calendar.MINUTE, 0);
long now = myCal.getTime().getTime();
assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,36 * TimeUtils.ONEHOUR), false, now));
assertEquals("2 days ago", timeUtils.timeAgo(offset(now,37 * TimeUtils.ONEHOUR), false, now));
assertEquals("2 days ago", timeUtils.timeAgo(offset(now,48 * TimeUtils.ONEHOUR), false, now));
assertEquals("2 days ago", timeUtils.timeAgo(offset(now,60 * TimeUtils.ONEHOUR), false, now));
assertEquals("3 days ago", timeUtils.timeAgo(offset(now,61 * TimeUtils.ONEHOUR), false, now));
assertEquals("3 days ago", timeUtils.timeAgo(offset(now,72 * TimeUtils.ONEHOUR), false, now));
assertEquals("3 days ago", timeUtils.timeAgo(offset(now,84 * TimeUtils.ONEHOUR), false, now));
assertEquals("4 days ago", timeUtils.timeAgo(offset(now,85 * TimeUtils.ONEHOUR), false, now));
}
@Test
public void testTimeAgoDaysAgoCET() throws Exception {
TimeZone myTimezone = TimeZone.getTimeZone("CET");
TimeUtils timeUtils = new TimeUtils(null, myTimezone);
Calendar myCal = Calendar.getInstance(myTimezone);
myCal.set(Calendar.HOUR_OF_DAY, 8);
myCal.set(Calendar.MINUTE, 0);
long now = myCal.getTime().getTime();
assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,32 * TimeUtils.ONEHOUR), false, now));
assertEquals("2 days ago", timeUtils.timeAgo(offset(now,33 * TimeUtils.ONEHOUR), false, now));
assertEquals("2 days ago", timeUtils.timeAgo(offset(now,48 * TimeUtils.ONEHOUR), false, now));
assertEquals("2 days ago", timeUtils.timeAgo(offset(now,56 * TimeUtils.ONEHOUR), false, now));
assertEquals("3 days ago", timeUtils.timeAgo(offset(now,57 * TimeUtils.ONEHOUR), false, now));
assertEquals("3 days ago", timeUtils.timeAgo(offset(now,72 * TimeUtils.ONEHOUR), false, now));
assertEquals("3 days ago", timeUtils.timeAgo(offset(now,80 * TimeUtils.ONEHOUR), false, now));
assertEquals("4 days ago", timeUtils.timeAgo(offset(now,81 * TimeUtils.ONEHOUR), false, now));
}
@Test
public void testTimeAgoDaysAgoPST() throws Exception {
TimeZone myTimezone = TimeZone.getTimeZone("PST");
TimeUtils timeUtils = new TimeUtils(null, myTimezone);
Calendar myCal = Calendar.getInstance(myTimezone);
myCal.set(Calendar.HOUR_OF_DAY, 22);
myCal.set(Calendar.MINUTE, 0);
long now = myCal.getTime().getTime();
assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now));
assertEquals("yesterday", timeUtils.timeAgo(offset(now,46 * TimeUtils.ONEHOUR), false, now));
assertEquals("2 days ago", timeUtils.timeAgo(offset(now,47 * TimeUtils.ONEHOUR), false, now));
assertEquals("2 days ago", timeUtils.timeAgo(offset(now,48 * TimeUtils.ONEHOUR), false, now));
assertEquals("2 days ago", timeUtils.timeAgo(offset(now,70 * TimeUtils.ONEHOUR), false, now));
assertEquals("3 days ago", timeUtils.timeAgo(offset(now,71 * TimeUtils.ONEHOUR), false, now));
assertEquals("3 days ago", timeUtils.timeAgo(offset(now,72 * TimeUtils.ONEHOUR), false, now));
assertEquals("3 days ago", timeUtils.timeAgo(offset(now,94 * TimeUtils.ONEHOUR), false, now));
assertEquals("4 days ago", timeUtils.timeAgo(offset(now,95 * TimeUtils.ONEHOUR), false, now));
}
/*
* Test if time difference is correctly calculated in full calendar days relative to GMT.
*/
@Test
public void testCalendarDaysAgoToGmt() {
TimeZone myTimezone = TimeZone.getTimeZone("GMT");
Calendar myCal = Calendar.getInstance(myTimezone);
myCal.set(2021, Calendar.AUGUST, 19, 12, 0, 5);
long now = myCal.getTime().getTime();
// Date from the same time zone
assertEquals(0, TimeUtils.calendarDaysAgo(offset(now, 11 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(0, TimeUtils.calendarDaysAgo(offset(now, 12 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(1, TimeUtils.calendarDaysAgo(offset(now, 12 * TimeUtils.ONEHOUR + 1 * TimeUtils.MIN), myTimezone, now));
assertEquals(1, TimeUtils.calendarDaysAgo(offset(now, 24 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(1, TimeUtils.calendarDaysAgo(offset(now, 36 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(2, TimeUtils.calendarDaysAgo(offset(now, 36 * TimeUtils.ONEHOUR + 10 * 1000), myTimezone, now));
assertEquals(2, TimeUtils.calendarDaysAgo(offset(now, 48 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(2, TimeUtils.calendarDaysAgo(offset(now, 60 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(3, TimeUtils.calendarDaysAgo(offset(now, 61 * TimeUtils.ONEHOUR ), myTimezone, now));
// What if we get passed a date created from a UTC timestamp that came from a different time zone?
// CET in August is +2 hours from GMT (CEST). So the day border is shifted two hours forward
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("CET"));
cal.set(2021, Calendar.AUGUST, 19, 8, 0, 5);
Date date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 19, 2, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 19, 1, 30, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 18, 12, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 18, 2, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 18, 0, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 17, 23, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 17, 3, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 17, 1, 0, 5);
date = cal.getTime();
assertEquals(3, TimeUtils.calendarDaysAgo(date, myTimezone, now));
// Now we travel westwards.
// PST in August is -7 hours from GMT (PDT). So the day border is shifted seven hours back
cal = Calendar.getInstance(TimeZone.getTimeZone("PST"));
cal.clear();
cal.set(2021, Calendar.AUGUST, 19, 5, 0, 0);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 19, 0, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 18, 17, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 18, 16, 55, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 18, 12, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 17, 17, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 17, 16, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 17, 1, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 16, 17, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2021, Calendar.AUGUST, 16, 14, 0, 5);
date = cal.getTime();
assertEquals(3, TimeUtils.calendarDaysAgo(date, myTimezone, now));
}
/*
* Test if time difference is correctly calculated in full calendar days relative to CET.
*/
@Test
public void testCalendarDaysAgoToCet() {
TimeZone myTimezone = TimeZone.getTimeZone("CET");
Calendar myCal = Calendar.getInstance(myTimezone);
myCal.set(2020, Calendar.JUNE, 5, 12, 0, 5);
long now = myCal.getTime().getTime();
// Date from the same time zone
assertEquals(0, TimeUtils.calendarDaysAgo(offset(now, 11 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(0, TimeUtils.calendarDaysAgo(offset(now, 12 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(1, TimeUtils.calendarDaysAgo(offset(now, 12 * TimeUtils.ONEHOUR + 1 * TimeUtils.MIN), myTimezone, now));
assertEquals(1, TimeUtils.calendarDaysAgo(offset(now, 24 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(1, TimeUtils.calendarDaysAgo(offset(now, 36 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(2, TimeUtils.calendarDaysAgo(offset(now, 36 * TimeUtils.ONEHOUR + 10 * 1000), myTimezone, now));
assertEquals(2, TimeUtils.calendarDaysAgo(offset(now, 48 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(2, TimeUtils.calendarDaysAgo(offset(now, 60 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(3, TimeUtils.calendarDaysAgo(offset(now, 61 * TimeUtils.ONEHOUR ), myTimezone, now));
// What if we get passed a date created from a UTC timestamp that came from a different time zone?
// IST in June is +3:30 hours from CEST. So the day border is shifted three and a half hours forward
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("IST"));
cal.set(2020, Calendar.JUNE, 5, 13, 0, 5);
Date date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 5, 3, 30, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 5, 3, 29, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 5, 0, 0, 0);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 4, 10, 0, 0);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 4, 4, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 4, 3, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 3, 12, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 3, 4, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 3, 3, 20, 5);
date = cal.getTime();
assertEquals(3, TimeUtils.calendarDaysAgo(date, myTimezone, now));
// Now we travel westwards to New York.
// EST in June is -6 hours from CEST (EDT). So the day border is shifted six hours back
cal = Calendar.getInstance(TimeZone.getTimeZone("EST5EDT"));
cal.clear();
cal.set(2020, Calendar.JUNE, 5, 5, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 5, 0, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 4, 18, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 4, 17, 59, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 4, 12, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 3, 19, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 3, 17, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 3, 8, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 2, 18, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2020, Calendar.JUNE, 2, 17, 20, 5);
date = cal.getTime();
assertEquals(3, TimeUtils.calendarDaysAgo(date, myTimezone, now));
}
/*
* Test if time difference is correctly calculated in full calendar days relative to AET (Australia).
*/
@Test
public void testCalendarDaysAgoToAet() {
TimeZone myTimezone = TimeZone.getTimeZone("AET");
Calendar myCal = Calendar.getInstance(myTimezone);
myCal.set(2022, Calendar.FEBRUARY, 22, 12, 0, 5);
long now = myCal.getTime().getTime();
// Date from the same time zone
assertEquals(0, TimeUtils.calendarDaysAgo(offset(now, 11 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(0, TimeUtils.calendarDaysAgo(offset(now, 12 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(1, TimeUtils.calendarDaysAgo(offset(now, 12 * TimeUtils.ONEHOUR + 1 * TimeUtils.MIN), myTimezone, now));
assertEquals(1, TimeUtils.calendarDaysAgo(offset(now, 24 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(1, TimeUtils.calendarDaysAgo(offset(now, 36 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(2, TimeUtils.calendarDaysAgo(offset(now, 36 * TimeUtils.ONEHOUR + 10 * 1000), myTimezone, now));
assertEquals(2, TimeUtils.calendarDaysAgo(offset(now, 48 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(2, TimeUtils.calendarDaysAgo(offset(now, 60 * TimeUtils.ONEHOUR ), myTimezone, now));
assertEquals(3, TimeUtils.calendarDaysAgo(offset(now, 61 * TimeUtils.ONEHOUR ), myTimezone, now));
// What if we get passed a date created from a UTC timestamp that came from a different time zone?
// NZ in February is +2 hours from AEDT. So the day border is shifted two hours forward
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("NZ"));
cal.set(2022, Calendar.FEBRUARY, 22, 12, 0, 5);
Date date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 22, 2, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 22, 1, 45, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 21, 22, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 21, 12, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 21, 2, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 21, 1, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 20, 10, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 20, 2, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 20, 1, 0, 5);
date = cal.getTime();
assertEquals(3, TimeUtils.calendarDaysAgo(date, myTimezone, now));
// Now we travel westwards to Europe.
// CET in February is -10 hours from AEDT. So the day border is shifted ten hours back
cal = Calendar.getInstance(TimeZone.getTimeZone("CET"));
cal.clear();
cal.set(2022, Calendar.FEBRUARY, 22, 2, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 22, 0, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 21, 14, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 21, 13, 30, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 21, 7, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 20, 15, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 20, 13, 59, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 20, 1, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 19, 14, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 19, 9, 0, 5);
date = cal.getTime();
assertEquals(3, TimeUtils.calendarDaysAgo(date, myTimezone, now));
// Lets continue even further west.
// AST in February is -15 hours from AEDT. So the day border is shifted fifteen hours back
cal = Calendar.getInstance(TimeZone.getTimeZone("America/Curacao"));
cal.clear();
cal.set(2022, Calendar.FEBRUARY, 21, 21, 0, 0);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 21, 12, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 21, 9, 0, 5);
date = cal.getTime();
assertEquals(0, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 21, 8, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 20, 19, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 20, 10, 0, 5);
date = cal.getTime();
assertEquals(1, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 20, 8, 50, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 19, 17, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 19, 9, 0, 5);
date = cal.getTime();
assertEquals(2, TimeUtils.calendarDaysAgo(date, myTimezone, now));
cal.set(2022, Calendar.FEBRUARY, 19, 7, 0, 5);
date = cal.getTime();
assertEquals(3, TimeUtils.calendarDaysAgo(date, myTimezone, now));
}
}
package com.gitblit.wicket;
import org.junit.Test;
import java.util.Locale;
import java.util.ResourceBundle;
import static org.junit.Assert.*;
public class GitBlitWebAppResourceBundleTest
{
@Test
public void testDefaultResource()
{
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp");
assertNotNull(bundle);
assertEquals("default", bundle.getString("gb.loadLang"));
}
@Test
public void testCsResource()
{
Locale l = Locale.forLanguageTag("cs");
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("čeština", bundle.getString("gb.loadLang"));
}
@Test
public void testDeResource()
{
Locale l = Locale.GERMAN;
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("Deutsch", bundle.getString("gb.loadLang"));
}
@Test
public void testEnResource()
{
Locale l = Locale.ENGLISH;
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
// The "en" file is just a placeholder for the default one.
assertEquals("default", bundle.getString("gb.loadLang"));
}
@Test
public void testEsResource()
{
Locale l = Locale.forLanguageTag("es");
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("Español", bundle.getString("gb.loadLang"));
}
@Test
public void testFrResource() throws Exception
{
Locale l = Locale.FRENCH;
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("français", bundle.getString("gb.loadLang"));
}
@Test
public void testItResource() throws Exception
{
Locale l = Locale.ITALIAN;
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("Italiano", bundle.getString("gb.loadLang"));
}
@Test
public void testJaResource() throws Exception
{
Locale l = Locale.JAPANESE;
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("にほんご", bundle.getString("gb.loadLang"));
}
@Test
public void testKoResource() throws Exception
{
Locale l = Locale.KOREAN;
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("한국어", bundle.getString("gb.loadLang"));
}
@Test
public void testNlResource() throws Exception
{
Locale l = Locale.forLanguageTag("nl");
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("Nederlands", bundle.getString("gb.loadLang"));
}
@Test
public void testNoResource() throws Exception
{
Locale l = Locale.forLanguageTag("no");
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("Norsk", bundle.getString("gb.loadLang"));
}
@Test
public void testPlResource() throws Exception
{
Locale l = Locale.forLanguageTag("pl");
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("polszczyzna", bundle.getString("gb.loadLang"));
}
@Test
public void testPtBrResource() throws Exception
{
Locale l = Locale.forLanguageTag("pt-BR");
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("Português", bundle.getString("gb.loadLang"));
}
@Test
public void testRuResource() throws Exception
{
Locale l = Locale.forLanguageTag("ru");
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("Русский", bundle.getString("gb.loadLang"));
}
@Test
public void testZhCnResource() throws Exception
{
Locale l = Locale.SIMPLIFIED_CHINESE;
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("汉字", bundle.getString("gb.loadLang"));
}
@Test
public void testZhTwResource() throws Exception
{
Locale l = Locale.TRADITIONAL_CHINESE;
ResourceBundle bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", l);
assertNotNull(bundle);
assertEquals("漢字", bundle.getString("gb.loadLang"));
}
}
package com.gitblit.wicket;
import static org.junit.Assert.*;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.gitblit.manager.IManager;
import com.gitblit.manager.IPluginManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.PluginRegistry;
import com.gitblit.tests.mock.MockGitblitContext;
import com.gitblit.tests.mock.MockRuntimeManager;
import org.apache.wicket.util.tester.WicketTester;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Before;
import org.junit.Test;
import com.gitblit.Keys;
import com.gitblit.tests.mock.MemorySettings;
import com.gitblit.utils.JSoupXssFilter;
import com.gitblit.wicket.MarkupProcessor.MarkupDocument;
import ro.fortsoft.pf4j.PluginState;
import ro.fortsoft.pf4j.PluginWrapper;
import ro.fortsoft.pf4j.Version;
public class MarkupProcessorTest
{
private WicketTester tester;
private MockGitblitContext gbctx;
@Before
public void setUp()
{
IRuntimeManager rm = new MockRuntimeManager(getSettings());
gbctx = new MockGitblitContext();
gbctx.addManager(rm);
tester = new WicketTester(new GitBlitWebApp(null, null,
rm,
getPluginManager(),
null, null, null,
null, null, null,
null, null, null));
}
/*
* The unit tests for MarkupProcessor have two major goals.
* One is to check that links are rendered correctly, and
* the second one is that XSS protection is working.
*
* The proper rendering of markup for the various Wiki/Markdown
* languages is not in focus. This, as a secondary goal, the Wiki/Md
* syntax rendering can be tested to make sure that when switching to
* a new or updated wiki syntax library nothing breaks and the pages
* are still rendered correctly.
* Or, to make sure things actually render correctly, because currently
* they don't as cen be seen with reference images and wiki links,
* for example.
*/
@Test
public void testParseMdRepoRelativeLink()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a page](file.md)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/file.md", href);
}
@Test
public void testParseMdRepoRelativeLinkSubfolder()
{
String psep ="%2F";
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a file](folder/file.md)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/folder"+psep+"file.md", href);
}
@Test
public void testParseMdRepoRelativeLinkSubSubfolder()
{
String psep ="%2F";
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a file](sub/folder/file.md)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/sub"+psep+"folder"+psep+"file.md", href);
}
@Test
public void testParseMdRepoRelativeLinkUtf8()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a page](日本語.md)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/%E6%97%A5%E6%9C%AC%E8%AA%9E.md", href);
}
@Test
public void testParseMdRepoRelativeLinkSubfolderUtf8()
{
String psep ="%2F";
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a file](folder/receitas_de_culinária/file.md)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/folder"+psep+"receitas_de_culin%C3%A1ria"+psep+"file.md", href);
}
@Test
public void testParseMdExternalLink()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a website](http://example.com/page.html)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","http://example.com/page.html", href);
}
@Test
public void testParseMdExternalLinkBare()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: <http://example.com/page.html>";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","http://example.com/page.html", href);
}
// We leave it up to the document author to write working links in the document
@Test
public void testParseMdExternalLinkUtf8()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [Japanese](http://example.com/lang/日本語.html)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","http://example.com/lang/日本語.html", href);
}
@Test
public void testParseMdRepoRelativeRefLink()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a page][1]\n\n[1]: file.md";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/file.md", href);
}
@Test
public void testParseMdRepoRelativeRefLinkSubfolder()
{
String psep ="%2F";
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a file][file]\n\n[file]: folder/file.md";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/folder"+psep+"file.md", href);
}
@Test
public void testParseMdRepoRelativeRefLinkSubSubfolder()
{
String psep ="%2F";
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a file][l1] \n\n[l1]: sub/folder/file.md";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/sub"+psep+"folder"+psep+"file.md", href);
}
@Test
public void testParseMdRepoRelativeRefLinkUtf8()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a page][x]\n\n[x]: 日本語.md";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/%E6%97%A5%E6%9C%AC%E8%AA%9E.md", href);
}
@Test
public void testParseMdRepoRelativeRefLinkSubfolderUtf8()
{
String psep ="%2F";
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a file][xy]\n\n[xy]: folder/receitas_de_culinária/file.md";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/folder"+psep+"receitas_de_culin%C3%A1ria"+psep+"file.md", href);
}
@Test
public void testParseMdExternalRefLink()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [a website][ex]\n\n[ex]: http://example.com/page.html";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","http://example.com/page.html", href);
}
/*
* Apparently wiki style links currently do not work in Markdown.
@Test
public void testParseMdWikiLink()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "link: [[page]]";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/testrepo/12345abcde/page", href);
}
*/
@Test
public void testParseMdRepoRelativeImage()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "image: ![a graphic](graphic.gif)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/graphic.gif", ref);
markup = "image: ![a graphic](graphic.gif \"Some graphic\")";
mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
doc = Jsoup.parseBodyFragment(mdoc.html);
ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/graphic.gif", ref);
}
@Test
public void testParseMdRepoRelativeImageUtf8()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "image: ![look the dog](ドッグ.gif)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/%E3%83%89%E3%83%83%E3%82%B0.gif", ref);
markup = "image: ![look the dog](ドッグ.gif \"シーバ\")";
mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
doc = Jsoup.parseBodyFragment(mdoc.html);
ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/%E3%83%89%E3%83%83%E3%82%B0.gif", ref);
}
@Test
public void testParseMdRepoRelativeImageSubfolder()
{
String psep ="!";
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "image: ![a graphic](results/graphic.gif)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/results"+psep+"graphic.gif", ref);
markup = "image: ![a graphic](results/graphic.gif \"Some graphic\")";
mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
doc = Jsoup.parseBodyFragment(mdoc.html);
ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/results"+psep+"graphic.gif", ref);
}
@Test
public void testParseMdRepoRelativeImageSubfolderUtf8()
{
String psep ="!";
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "image: ![a cat](folder/картинки/cat.jpg)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/folder"+psep+"%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BA%D0%B8"+psep+"cat.jpg", ref);
markup = "image: ![a cat](folder/картинки/cat.jpg \"Кошка\")";
mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
doc = Jsoup.parseBodyFragment(mdoc.html);
ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/folder"+psep+"%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BA%D0%B8"+psep+"cat.jpg", ref);
}
@Test
public void testParseMdExternalImage()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "image: ![a cat](http://example.com/cats/meow.jpg)";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","http://example.com/cats/meow.jpg", ref);
markup = "image: ![a cat](http://example.com/cats/meow.jpg \"Miau\")";
mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
doc = Jsoup.parseBodyFragment(mdoc.html);
ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","http://example.com/cats/meow.jpg", ref);
}
@Test
public void testParseMdRepoRelativeRefImage()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "image: ![a graphic][1]\n\n[1]: graphic.gif";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/graphic.gif", ref);
markup = "image: ![a graphic][2]\n\n[2]: graphic.gif \"Some graphic\"";
mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
doc = Jsoup.parseBodyFragment(mdoc.html);
ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/graphic.gif", ref);
}
@Test
public void testParseMdRepoRelativeRefImageUtf8()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "image: ![look the dog][1]\n\n[1]: ドッグ.gif";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/%E3%83%89%E3%83%83%E3%82%B0.gif", ref);
markup = "image: ![look the dog][1]\n\n[1]: ドッグ.gif \"シーバ\"";
mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
doc = Jsoup.parseBodyFragment(mdoc.html);
ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/%E3%83%89%E3%83%83%E3%82%B0.gif", ref);
}
@Test
public void testParseMdRepoRelativeRefImageSubfolder()
{
String psep ="!";
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "image: ![a cat][cat]\n\n[cat]: folder/cat.jpg";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/folder"+psep+"cat.jpg", ref);
markup = "image: ![a cat][cat]\n\n[cat]: folder/cat.jpg \"Кошка\"";
mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
doc = Jsoup.parseBodyFragment(mdoc.html);
ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/folder"+psep+"cat.jpg", ref);
}
@Test
public void testParseMdRepoRelativeRefImageSubfolderUtf8()
{
String psep ="!";
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "image: ![a cat][i1]\n\n[i1]: folder/картинки/cat.jpg";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/folder"+psep+"%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BA%D0%B8"+psep+"cat.jpg", ref);
markup = "image: ![a cat][i1]\n\n[i1]: folder/картинки/cat.jpg \"Кошка\"";
mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
doc = Jsoup.parseBodyFragment(mdoc.html);
ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","../raw/testrepo/12345abcde/folder"+psep+"%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BA%D0%B8"+psep+"cat.jpg", ref);
}
@Test
public void testParseMdExternalRefImage()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String markup = "image: ![a cat][1]\n\n[1]: http://example.com/cats/meow.jpg";
MarkupDocument mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","http://example.com/cats/meow.jpg", ref);
markup = "image: ![a cat][1]\n\n[1]: http://example.com/cats/meow.jpg \"Miau\"";
mdoc = mp.parse("testrepo", "12345abcde", "main.md", markup);
doc = Jsoup.parseBodyFragment(mdoc.html);
ref = doc.getElementsByAttribute("src").attr("src");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect image src rendered","http://example.com/cats/meow.jpg", ref);
}
@Test
public void testParseMediaWikiRepoRelativeLink()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String psep = "%2F";
String markup = "link: [[document]]";
MarkupDocument mdoc = mp.parse("wikirepo", "12345abcde", "main.mw", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("href").attr("href");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect link href rendered","doc/wikirepo/12345abcde/wiki"+ psep + "document", ref);
}
@Test
public void testParseMediaWikiRepoRelativeLinkUtf8()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String psep = "%2F";
String markup = "link: [[日本語]]";
MarkupDocument mdoc = mp.parse("wikirepo", "12345abcde", "main.mw", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","doc/wikirepo/12345abcde/wiki" + psep + "%E6%97%A5%E6%9C%AC%E8%AA%9E", href);
}
@Test
public void testParseMediaWikiExternalLink()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String psep = "%2F";
String markup = "link: [http://example.com/some/document.html document]";
MarkupDocument mdoc = mp.parse("wikirepo", "12345abcde", "main.mw", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("href").attr("href");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect link href rendered","http://example.com/some/document.html", ref);
}
@Test
public void testParseMediaWikiExternalLinkNumbered()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String psep = "%2F";
String markup = "link: [http://example.com/some/document.html]";
MarkupDocument mdoc = mp.parse("wikirepo", "12345abcde", "main.mw", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("href").attr("href");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect link href rendered","http://example.com/some/document.html", ref);
}
@Test
public void testParseMediaWikiExternalLinkBare()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String psep = "%2F";
String markup = "link: http://example.com/some/document.html";
MarkupDocument mdoc = mp.parse("wikirepo", "12345abcde", "main.mw", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String ref = doc.getElementsByAttribute("href").attr("href");
assertFalse("No reference attribute found: " + mdoc.html, ref.isEmpty());
assertEquals("Incorrect link href rendered","http://example.com/some/document.html", ref);
}
// We leave it up to the document author to write working links in the document
@Test
public void testParseMediaWikiExternalLinkUtf8()
{
MarkupProcessor mp = new MarkupProcessor(getSettings(), new JSoupXssFilter());
String psep = "%2F";
String markup = "link: [http://example.com/lang/日本語.html Japanese]";
MarkupDocument mdoc = mp.parse("wikirepo", "12345abcde", "main.mw", markup);
Document doc = Jsoup.parseBodyFragment(mdoc.html);
String href = doc.getElementsByAttribute("href").attr("href");
assertEquals("Incorrect link rendered","http://example.com/lang/日本語.html", href);
}
private MemorySettings getSettings()
{
Map<String, Object> backingMap = new HashMap<String, Object>();
backingMap.put(Keys.web.documents, "readme");
backingMap.put(Keys.web.blobEncodings, "UTF-8 ISO-8859-1");
backingMap.put(Keys.web.confluenceExtensions, "confluence");
backingMap.put(Keys.web.markdownExtensions, "md mkd markdown MD MKD");
backingMap.put(Keys.web.mediawikiExtensions, "mw mediawiki");
backingMap.put(Keys.web.textileExtensions, "textile");
backingMap.put(Keys.web.tracwikiExtensions, "tracwiki");
backingMap.put(Keys.web.twikiExtensions, "twiki");
backingMap.put(Keys.web.forwardSlashCharacter, "/");
backingMap.put(Keys.web.mountParameters, true);
MemorySettings ms = new MemorySettings(backingMap);
return ms;
}
private IPluginManager getPluginManager()
{
return new IPluginManager()
{
@Override
public Version getSystemVersion()
{
return null;
}
@Override
public void startPlugins()
{
}
@Override
public void stopPlugins()
{
}
@Override
public PluginState startPlugin(String pluginId)
{
return null;
}
@Override
public PluginState stopPlugin(String pluginId)
{
return null;
}
@Override
public List<Class<?>> getExtensionClasses(String pluginId)
{
return null;
}
@Override
public <T> List<T> getExtensions(Class<T> type)
{
return null;
}
@Override
public List<PluginWrapper> getPlugins()
{
return Collections.emptyList();
}
@Override
public PluginWrapper getPlugin(String pluginId)
{
return null;
}
@Override
public PluginWrapper whichPlugin(Class<?> clazz)
{
return null;
}
@Override
public boolean disablePlugin(String pluginId)
{
return false;
}
@Override
public boolean enablePlugin(String pluginId)
{
return false;
}
@Override
public boolean uninstallPlugin(String pluginId)
{
return false;
}
@Override
public boolean refreshRegistry(boolean verifyChecksum)
{
return false;
}
@Override
public boolean installPlugin(String url, boolean verifyChecksum) throws IOException
{
return false;
}
@Override
public boolean upgradePlugin(String pluginId, String url, boolean verifyChecksum) throws IOException
{
return false;
}
@Override
public List<PluginRegistry.PluginRegistration> getRegisteredPlugins()
{
return null;
}
@Override
public List<PluginRegistry.PluginRegistration> getRegisteredPlugins(PluginRegistry.InstallState state)
{
return null;
}
@Override
public PluginRegistry.PluginRegistration lookupPlugin(String idOrName)
{
return null;
}
@Override
public PluginRegistry.PluginRelease lookupRelease(String idOrName, String version)
{
return null;
}
@Override
public IManager start()
{
return null;
}
@Override
public IManager stop()
{
return null;
}
};
}
}
+22
-2

@@ -24,4 +24,5 @@ gbsteps: &gbsteps

version: 2
version: 2.1
jobs:

@@ -50,4 +51,23 @@ buildJ8:

jobs:
- "buildJ8"
- buildJ8:
post-steps:
- run:
name: Upload coverage to Codecov
command: bash <(curl -s https://codecov.io/bash)
- run:
name: Prepare Code Climate coverage reporter
command: |
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
chmod +x ./cc-test-reporter
./cc-test-reporter before-build
- run:
name: Upload coverage to Code Climate
command: |
JACOCO_SOURCE_PATH=src/main/java ./cc-test-reporter format-coverage ./build/target/reports/coverage/jacoco.xml --input-type jacoco
./cc-test-reporter upload-coverage
when: on_success
- run:
name: Upload coverage to Codacy
command: bash <(curl -Ls https://coverage.codacy.com/get.sh) report
- "buildJ9"
- "buildJ11"
+166
-50
<?xml version="1.0" encoding="UTF-8"?>
<project name="gitblit" default="compile" xmlns:mx="antlib:org.moxie">
<project name="gitblit" default="compile" xmlns:mx="antlib:org.moxie" xmlns:jacoco="antlib:org.jacoco.ant">

@@ -15,3 +15,5 @@ <!--

<property name="moxie.dir" value="${user.home}/.moxie" />
<property name="jacoco.version" value="0.8.4" />
<!-- Download Moxie from it's Maven repository to user.home -->

@@ -38,2 +40,4 @@ <mkdir dir="${moxie.dir}" />

<property name="gh.org" value="gitblit" />
<!-- GitHub project name -->
<property name="gh.repo" value="gitblit" />

@@ -51,3 +55,8 @@ <!--

<mx:init verbose="no" mxroot="${moxie.dir}" />
<!-- Register JaCoCo tasks -->
<taskdef uri="antlib:org.jacoco.ant">
<classpath location="${moxie.dir}/remote/repo1.maven.org_maven2/org/jacoco/org.jacoco.ant/${jacoco.version}/org.jacoco.ant-${jacoco.version}-nodeps.jar" />
</taskdef>
<!-- Set Ant project properties -->

@@ -70,2 +79,3 @@ <property name="release.tag" value="v${project.version}" />

<property name="gc.url" value="https://github.com/${gh.org}/gitblit/releases/download/" />
<property name="docker.url" value="https://hub.docker.com/r/gitblit/gitblit" />

@@ -78,2 +88,3 @@ <!-- Report Java version -->

<echo>Java/JVM version: ${java.version}</echo>
<echo>Github coordinates: ${gh.org}/${gh.repo}</echo>
</target>

@@ -168,3 +179,18 @@

<mx:test failonerror="true" />
<!-- Create JaCoCo single XML report file for code coverage service. -->
<jacoco:report>
<executiondata>
<file file="${project.outputDirectory}/jacoco.exec"/>
</executiondata>
<structure name="${project.name}">
<classfiles>
<fileset dir="${project.outputDirectory}/classes"/>
</classfiles>
<sourcefiles encoding="UTF-8">
<fileset dir="${project.src.dir}"/>
</sourcefiles>
</structure>
<xml destfile="${project.targetDirectory}/reports/coverage/jacoco.xml"/>
</jacoco:report>
</target>

@@ -589,3 +615,3 @@

<divider />
<link name="Gitblit GO (Docker)" src="https://registry.hub.docker.com/u/jmoger/gitblit/" />
<link name="Gitblit GO (Docker)" src="${docker.url}" />
<divider />

@@ -600,4 +626,3 @@ <link name="Plugins Registry" src="http://plugins.gitblit.com" />

<link name="GitHub (1.9.0+)" src="https://github.com/${gh.org}/gitblit/releases" />
<link name="Bintray (1.4.0-1.8.0)" src="https://bintray.com/gitblit/releases/gitblit" />
<link name="GoogleCode (pre-1.4.0)" src="https://code.google.com/p/gitblit/downloads/list?can=1" />
<link name="Cloudsmith (1.3.0-1.8.0)" src="https://cloudsmith.io/~gitblit/repos/gitblit/groups/" />
<divider />

@@ -616,3 +641,3 @@ <link name="Maven Repository" src="${project.mavenUrl}" />

<link name="Twitter" src="https://twitter.com/gitblit" />
<link name="Ohloh" src="http://www.ohloh.net/p/gitblit" />
<link name="OpenHub" src="https://www.openhub.net/p/gitblit" />
<divider />

@@ -627,5 +652,6 @@ <link name="Gitblit Tickets screencast" src="https://vimeo.com/86164723" />

</structure>
<replace token="%GCURL%" value="${gc.url}${currentRelease.tag}/" />
<replace token="%DOCKERURL%" value="${docker.url}" />
<properties token="%PROPERTIES%" file="${project.distrib.dir}/data/defaults.properties" />

@@ -815,3 +841,3 @@

<arg value="-c" />
<arg value="${octokit} -q edit_release ${gh.org} gitblit ${ghrelease.id} tag_name='${release.tag}'"></arg>
<arg value="${octokit} -q edit_release ${gh.org} ${gh.repo} ${ghrelease.id} tag_name='${release.tag}'"></arg>
</exec>

@@ -853,4 +879,35 @@ <ghPublishReleaseDraft

<!--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Determine the release version and tag name.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-->
<target name="determineReleaseVersion" depends="prepare" description="determine the release version and tag name">
<exec executable="bash" logError="true" outputproperty="determined_release.version">
<arg value="-c" />
<arg value="grep '^version:' build.moxie | sed -e 's/version: *//' -e 's/-SNAPSHOT//'"></arg>
</exec>
<property name="determined_release.tag" value="v${determined_release.version}" />
<echo>Release version: ${determined_release.version}</echo>
<echo>Release tag: ${determined_release.tag}</echo>
<!-- output version information for other scripts/programs to pick up -->
<mx:if>
<and>
<isset property="versionInfo" />
<not><equals arg1="${versionInfo}" arg2="" trim="true"/></not>
</and>
<then>
<echo file="${basedir}/${versionInfo}">
GBLT_RELEASE_VERSION=${determined_release.version}
GBLT_RELEASE_TAG=${determined_release.tag}
</echo>
</then>
</mx:if>
</target>
<!--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tag a new version and prepare for the next development cycle.

@@ -880,4 +937,4 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

<echo file="${basedir}/${versionInfo}">
GB_RELEASE_VERSION=${project.version}
GB_RELEASE_TAG=${project.tag}
GBLT_RELEASE_VERSION=${project.version}
GBLT_RELEASE_TAG=${project.tag}
</echo>

@@ -888,31 +945,24 @@ </then>

<!-- create the release process script -->
<mx:if>
<os family="windows" />
<then>
<!-- Windows PowerShell script -->
<!-- set-executionpolicy remotesigned -->
<property name="recipe" value="release_${project.version}.ps1" />
</then>
<else>
<!-- Bash script -->
<property name="recipe" value="release_${project.version}.sh" />
</else>
</mx:if>
<delete file="${recipe}" failonerror="false" quiet="true" verbose="false" />
<!-- Work-around for lack of proper ant property substitution in copy -->
<property name="dollar" value="$"/>
<copy file="release.template" tofile="${recipe}">
<filterset begintoken="${dollar}{" endtoken="}">
<filter token="project.version" value="${project.version}" />
<filter token="project.commitId" value="${project.commitId}" />
<filter token="project.tag" value="${project.tag}" />
<filter token="project.directory" value="${basedir}" />
<filter token="maven.directory" value="${maven.directory}" />
</filterset>
</copy>
<chmod file="${recipe}" perm="ugo+rx" />
<createReleaseScript
projectVersion="${project.version}"
projectTag="${project.tag}"
projectCommitId="${project.commitId}" />
</target>
<!--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create the release process script from the template.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-->
<target name="releaseScript" depends="prepare" description="create the release process script for a release version">
<!-- create the release process script -->
<createReleaseScript
projectVersion="${project.version}"
projectTag="${release.tag}"
projectCommitId="${release.tag}" />
</target>
<!--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@@ -944,3 +994,43 @@ Prepare for the next point release development cycle.

<!--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create the release process script from the template.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-->
<macrodef name="createReleaseScript">
<attribute name="projectVersion" />
<attribute name="projectTag" />
<attribute name="projectCommitId" />
<sequential>
<mx:if>
<os family="windows" />
<then>
<!-- Windows PowerShell script -->
<!-- set-executionpolicy remotesigned -->
<property name="recipe" value="release_@{projectVersion}.ps1" />
</then>
<else>
<!-- Bash script -->
<property name="recipe" value="release_@{projectVersion}.sh" />
</else>
</mx:if>
<delete file="${recipe}" failonerror="false" quiet="true" verbose="false" />
<!-- Work-around for lack of proper ant property substitution in copy -->
<property name="dollar" value="$"/>
<copy file="release.template" tofile="${recipe}">
<filterset begintoken="${dollar}{" endtoken="}">
<filter token="project.version" value="@{projectVersion}" />
<filter token="project.commitId" value="@{projectCommitId}" />
<filter token="project.tag" value="@{projectTag}" />
<filter token="project.directory" value="${basedir}" />
<filter token="maven.directory" value="${maven.directory}" />
</filterset>
</copy>
<chmod file="${recipe}" perm="ugo+rx" />
</sequential>
</macrodef>
<!--

@@ -1033,3 +1123,3 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

<link name="Twitter" src="https://twitter.com/gitblit" />
<link name="Ohloh" src="http://www.ohloh.net/p/gitblit" />
<link name="OpenHub" src="https://www.openhub.net/p/gitblit" />
</menu>

@@ -1039,2 +1129,3 @@ </structure>

<replace token="%GCURL%" value="${gc.url}${currentRelease.tag}/" />
<replace token="%DOCKERURL%" value="${docker.url}" />

@@ -1142,10 +1233,23 @@ <properties token="%PROPERTIES%" file="${project.distrib.dir}/data/defaults.properties" />

<sequential>
<echo>creating release ${release.tag} draft on GitHub</echo>
<exec executable="bash" logError="true" failonerror="true" outputproperty="ghrelease.id">
<arg value="-c" />
<arg value="${octokit} create_release ${gh.org} gitblit @{releasetag} name=${project.version} draft=true | cut -f2"></arg>
</exec>
<mx:if>
<isset property="updateRelease" />
<then>
<echo>updating release @{releasetag} draft on GitHub</echo>
<exec executable="bash" logError="true" failonerror="true" outputproperty="ghrelease.id">
<arg value="-c" />
<arg value="${octokit} list_releases ${gh.org} ${gh.repo} _filter='.[] | &quot;\(.name)\t\(.id)&quot;' | grep ${project.version} | cut -f2"></arg>
</exec>
</then>
<else>
<echo>creating release @{releasetag} draft on GitHub</echo>
<exec executable="bash" logError="true" failonerror="true" outputproperty="ghrelease.id">
<arg value="-c" />
<arg value="${octokit} create_release ${gh.org} ${gh.repo} @{releasetag} name=${project.version} draft=true | cut -f2"></arg>
</exec>
</else>
</mx:if>
<exec executable="bash" logError="true" failonerror="true" outputproperty="ghrelease.upldUrl">
<arg value="-c" />
<arg value="${octokit} release ${gh.org} gitblit ${ghrelease.id} _filter=.upload_url | sed 's/{.*$/?name=/'"></arg>
<arg value="${octokit} release ${gh.org} ${gh.repo} ${ghrelease.id} _filter=.upload_url | sed 's/{.*$/?name=/'"></arg>
</exec>

@@ -1158,3 +1262,3 @@ <exec executable="bash" logError="true" failonerror="true" outputproperty="ghrelease.notes">

<arg value="-c" />
<arg value="${octokit} -q edit_release ${gh.org} gitblit ${ghrelease.id} body='${ghrelease.notes}'"></arg>
<arg value="${octokit} -q edit_release ${gh.org} ${gh.repo} ${ghrelease.id} tag_name='@{releasetag}' body='${ghrelease.notes}'"></arg>
</exec>

@@ -1173,2 +1277,14 @@ </sequential>

<sequential>
<mx:if>
<isset property="updateRelease" />
<then>
<echo>removing @{target} on GitHub from release ${ghrelease.id}</echo>
<exec executable="bash" logError="true" failonerror="true">
<arg value="-c" />
<arg value="${octokit} release_assets ${gh.org} ${gh.repo} ${ghrelease.id} | grep @{target} | cut -f1 | xargs -L1 ${octokit} -y delete_asset ${gh.org} ${gh.repo}"></arg>
</exec>
</then>
<else>
</else>
</mx:if>
<echo>uploading @{source} to GitHub release ${ghrelease.id}</echo>

@@ -1193,3 +1309,3 @@ <exec executable="bash" logError="true" failonerror="true" >

<arg value="-c" />
<arg value="${octokit} -q edit_release ${gh.org} gitblit @{releaseid} draft=false"></arg>
<arg value="${octokit} -q edit_release ${gh.org} ${gh.repo} @{releaseid} draft=false"></arg>
</exec>

@@ -1209,3 +1325,3 @@ </sequential>

<arg value="-c" />
<arg value="${octokit} list_releases ${gh.org} gitblit _filter='.[] | &quot;\(.name)\t\(.tag_name)\t\(.id)&quot;' | grep @{releaseVersion} | cut -f3"></arg>
<arg value="${octokit} list_releases ${gh.org} ${gh.repo} _filter='.[] | &quot;\(.name)\t\(.tag_name)\t\(.id)&quot;' | grep @{releaseVersion} | cut -f3"></arg>
</exec>

@@ -1212,0 +1328,0 @@ </sequential>

@@ -19,4 +19,4 @@ #!/bin/bash

FOLDER=data/git
EXCLUSIONS=--skip test.git --skip group/test*
EXCLUSIONS="--skip test.git --skip group/test*"
BRANCH=default
java -cp gitblit.jar:"ext/*" com.gitblit.AddIndexedBranch --repositoriesFolder $FOLDER --branch $BRANCH $EXCLUSIONS
java -cp gitblit.jar:"ext/*" com.gitblit.AddIndexedBranch --repositoriesFolder "$FOLDER" --branch "$BRANCH" "$EXCLUSIONS"

@@ -20,3 +20,3 @@ #!/bin/bash

java -cp "gitblit.jar:ext/*" com.gitblit.MigrateTickets $1 --baseFolder $2
java -cp "gitblit.jar:ext/*" com.gitblit.MigrateTickets "$1" --baseFolder "$2"

@@ -23,3 +23,3 @@ #!/bin/bash

java -cp "gitblit.jar:ext/*" com.gitblit.ReindexTickets --baseFolder $1
java -cp "gitblit.jar:ext/*" com.gitblit.ReindexTickets --baseFolder "$1"

@@ -17,5 +17,9 @@ @REM --------------------------------------------------------------------------

@REM --------------------------------------------------------------------------
@SETLOCAL
@SET FOLDER=data/git
@SET EXCLUSIONS=--skip test.git --skip group/test*
@SET BRANCH=default
@PUSHD %~dp0
@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.AddIndexedBranch --repositoriesFolder %FOLDER% --branch %BRANCH% %EXCLUSIONS% %*
@POPD
@ENDLOCAL

@@ -1,1 +0,8 @@

@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.authority.GitblitAuthority --baseFolder data %*
@SETLOCAL
@SET gbhome=%~dp0
@SET gbhome=%gbhome:~0,-1%
@java -cp "%gbhome%\gitblit.jar";"%gbhome%\ext\*" com.gitblit.authority.GitblitAuthority --baseFolder "%gbhome%\data" %*
@ENDLOCAL

@@ -1,1 +0,1 @@

@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --stop --baseFolder data %*
@java -cp "%~dp0gitblit.jar";"%~dp0ext\*" com.gitblit.GitBlitServer --stop %*

@@ -1,1 +0,8 @@

@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.GitBlitServer --baseFolder data %*
@SETLOCAL
@SET gbhome=%~dp0
@SET gbhome=%gbhome:~0,-1%
@java -cp "%gbhome%\gitblit.jar";"%gbhome%\ext\*" com.gitblit.GitBlitServer --baseFolder "%gbhome%\data" %*
@ENDLOCAL

@@ -11,12 +11,17 @@ @REM Install Gitblit as a Windows service.

@SETLOCAL
@REM arch = x86, amd64, or ia32
SET ARCH=amd64
@SET gbhome=%~dp0
@SET gbhome=%gbhome:~0,-1%
@REM Be careful not to introduce trailing whitespace after the ^ characters.
@REM Use ; or # to separate values in the --StartParams parameter.
"%CD%\%ARCH%\gitblit.exe" //IS//gitblit ^
"%gbhome%\%ARCH%\gitblit.exe" //IS//gitblit ^
--DisplayName="gitblit" ^
--Description="a pure Java Git solution" ^
--Startup=auto ^
--LogPath="%CD%\logs" ^
--LogPath="%gbhome%\logs" ^
--LogLevel=INFO ^

@@ -26,15 +31,16 @@ --LogPrefix=gitblit ^

--StdError=auto ^
--StartPath="%CD%" ^
--StartPath="%gbhome%" ^
--StartClass=com.gitblit.GitBlitServer ^
--StartMethod=main ^
--StartParams="--storePassword;gitblit;--baseFolder;%CD%\data" ^
--StartParams="--storePassword;gitblit;--baseFolder;%gbhome%\data" ^
--StartMode=jvm ^
--StopPath="%CD%" ^
--StopPath="%gbhome%" ^
--StopClass=com.gitblit.GitBlitServer ^
--StopMethod=main ^
--StopParams="--stop;--baseFolder;%CD%\data" ^
--StopParams="--stop;--baseFolder;%gbhome%\data" ^
--StopMode=jvm ^
--Classpath="%CD%\gitblit.jar;%CD%\ext\*" ^
--Classpath="%gbhome%\gitblit.jar;%gbhome%\ext\*" ^
--Jvm=auto ^
--JvmMx=1024
@ENDLOCAL

@@ -12,11 +12,11 @@ @REM --------------------------------------------------------------------------

@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.MigrateTickets %1 --baseFolder %2
@java -cp "%~dp0gitblit.jar";"%~dp0ext\*" com.gitblit.MigrateTickets %1 --baseFolder %2
@goto end
:help
@echo "Please specify the output ticket service and your baseFolder!"
@echo
@echo " migrate-tickets com.gitblit.tickets.RedisTicketService c:/gitblit-data"
@echo
@echo Please specify the output ticket service and your baseFolder!
@echo.
@echo e.g.: migrate-tickets com.gitblit.tickets.RedisTicketService "c:/gitblit data"
@echo.
:end
:end

@@ -13,11 +13,11 @@ @REM --------------------------------------------------------------------------

@java -cp gitblit.jar;"%CD%\ext\*" com.gitblit.ReindexTickets --baseFolder %1
@java -cp "%~dp0gitblit.jar";"%~dp0ext\*" com.gitblit.ReindexTickets --baseFolder %1
@goto end
:nobasefolder
@echo "Please specify your baseFolder!"
@echo
@echo " reindex-tickets c:/gitblit-data"
@echo
@echo Please specify your baseFolder!
@echo.
@echo reindex-tickets c:/gitblit-data
@echo.
:end
:end

@@ -0,1 +1,3 @@

@SETLOCAL
@REM arch = x86, amd64, or ia32

@@ -5,2 +7,4 @@ SET ARCH=amd64

@REM Delete the gitblit service
"%CD%\%ARCH%\gitblit.exe" //DS//gitblit
"%~dp0%ARCH%\gitblit.exe" //DS//gitblit
@ENDLOCAL

@@ -679,3 +679,3 @@ /*

StoredConfig config = new FileBasedConfig(realmFileCopy, FS.detect());
StoredUserConfig config = new StoredUserConfig(realmFileCopy);

@@ -682,0 +682,0 @@ // write users

@@ -25,2 +25,3 @@ /*

import com.gitblit.utils.ContainerDetector;
import org.slf4j.Logger;

@@ -82,2 +83,3 @@ import org.slf4j.LoggerFactory;

logger.info("App locale : " + (getLocale() == null ? "<client>" : getLocale()));
ContainerDetector.report(logger, true);
return this;

@@ -84,0 +86,0 @@ }

@@ -39,14 +39,38 @@ /*

private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 876822269940583606L;
public final String displayName;
public final RevObject referencedObject;
public transient Ref reference;
private final Date date;
private final String name;
private final int type;
private final String id;
private final String referencedId;
private final boolean annotated;
private final PersonIdent person;
private final String shortMessage;
private final String fullMessage;
private transient ObjectId objectId;
private transient ObjectId referencedObjectId;
public transient Ref reference; // Used in too many places.
public RefModel(String displayName, Ref ref, RevObject refObject) {
this.reference = ref;
this.displayName = displayName;
this.reference = ref;
this.referencedObject = refObject;
this.date = internalGetDate(refObject);
this.name = ref != null ? ref.getName() : displayName;
this.type = internalGetReferencedObjectType(refObject);
this.objectId = ref != null ? ref.getObjectId() : ObjectId.zeroId();
this.id = this.objectId.getName();
this.referencedObjectId = internalGetReferencedObjectId(refObject);
this.referencedId = this.referencedObjectId.getName();
this.annotated = internalIsAnnotatedTag(ref, refObject);
this.person = internalGetAuthorIdent(refObject);
this.shortMessage = internalGetShortMessage(refObject);
this.fullMessage = internalGetFullMessage(refObject);
}
public Date getDate() {
private Date internalGetDate(RevObject referencedObject) {
Date date = new Date(0);

@@ -68,10 +92,11 @@ if (referencedObject != null) {

public Date getDate() {
return date;
}
public String getName() {
if (reference == null) {
return displayName;
}
return reference.getName();
return name;
}
public int getReferencedObjectType() {
private int internalGetReferencedObjectType(RevObject referencedObject) {
int type = referencedObject.getType();

@@ -84,3 +109,7 @@ if (referencedObject instanceof RevTag) {

public ObjectId getReferencedObjectId() {
public int getReferencedObjectType() {
return type;
}
private ObjectId internalGetReferencedObjectId(RevObject referencedObject) {
if (referencedObject instanceof RevTag) {

@@ -92,3 +121,10 @@ return ((RevTag) referencedObject).getObject().getId();

public String getShortMessage() {
public ObjectId getReferencedObjectId() {
if (referencedObjectId == null) {
referencedObjectId = ObjectId.fromString(referencedId);
}
return referencedObjectId;
}
private String internalGetShortMessage(RevObject referencedObject) {
String message = "";

@@ -103,3 +139,7 @@ if (referencedObject instanceof RevTag) {

public String getFullMessage() {
public String getShortMessage() {
return shortMessage;
}
private String internalGetFullMessage(RevObject referencedObject) {
String message = "";

@@ -114,3 +154,7 @@ if (referencedObject instanceof RevTag) {

public PersonIdent getAuthorIdent() {
public String getFullMessage() {
return fullMessage;
}
private PersonIdent internalGetAuthorIdent(RevObject referencedObject) {
if (referencedObject instanceof RevTag) {

@@ -124,13 +168,24 @@ return ((RevTag) referencedObject).getTaggerIdent();

public PersonIdent getAuthorIdent() {
return person;
}
public ObjectId getObjectId() {
return reference.getObjectId();
if (objectId == null) {
objectId = ObjectId.fromString(id);
}
return objectId;
}
public boolean isAnnotatedTag() {
private boolean internalIsAnnotatedTag(Ref reference, RevObject referencedObject) {
if (referencedObject instanceof RevTag) {
return !getReferencedObjectId().equals(getObjectId());
}
return reference.getPeeledObjectId() != null;
return reference != null && reference.getPeeledObjectId() != null;
}
public boolean isAnnotatedTag() {
return annotated;
}
@Override

@@ -137,0 +192,0 @@ public int hashCode() {

@@ -18,2 +18,4 @@ /*

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

@@ -26,7 +28,10 @@ import java.text.MessageFormat;

import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import com.gitblit.wicket.GitBlitWebApp;
/**
* Model class to represent a RevCommit, it's source repository, and the branch.
* This class is used by the activity page.
* Model class to represent a RevCommit, it's source repository, and the branch. This class is used by the activity page.
*

@@ -37,12 +42,14 @@ * @author James Moger

private static final long serialVersionUID = 1L;
private static final long serialVersionUID = -2214911650485772022L;
public final String repository;
public String repository;
public final String branch;
public String branch;
private final RevCommit commit;
private final String commitId;
private List<RefModel> refs;
private transient RevCommit commit;
public RepositoryCommit(String repository, String branch, RevCommit commit) {

@@ -52,2 +59,3 @@ this.repository = repository;

this.commit = commit;
this.commitId = commit.getName();
}

@@ -87,3 +95,3 @@

public RevCommit [] getParents() {
public RevCommit[] getParents() {
return commit.getParents();

@@ -100,6 +108,10 @@ }

public RevCommit getCommit() {
return commit;
}
@Override
public boolean equals(Object o) {
if (o instanceof RepositoryCommit) {
RepositoryCommit commit = (RepositoryCommit) o;
final RepositoryCommit commit = (RepositoryCommit) o;
return repository.equals(commit.repository) && getName().equals(commit.getName());

@@ -132,6 +144,21 @@ }

public String toString() {
return MessageFormat.format("{0} {1} {2,date,yyyy-MM-dd HH:mm} {3} {4}",
getShortName(), branch, getCommitterIdent().getWhen(), getAuthorIdent().getName(),
getShortMessage());
return MessageFormat.format("{0} {1} {2,date,yyyy-MM-dd HH:mm} {3} {4}", getShortName(), branch, getCommitterIdent().getWhen(),
getAuthorIdent().getName(), getShortMessage());
}
// Serialization: restore the JGit RevCommit on reading
private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException {
// Read in fields and any hidden stuff
input.defaultReadObject();
// Go find the commit again.
final Repository repo = GitBlitWebApp.get().repositories().getRepository(repository);
if (repo == null) {
throw new IOException("Cannot find repositoy " + repository);
}
try (RevWalk walk = new RevWalk(repo)) {
commit = walk.parseCommit(repo.resolve(commitId));
}
}
}

@@ -30,2 +30,3 @@ /*

import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.FetchResult;

@@ -36,2 +37,4 @@ import org.eclipse.jgit.transport.ReceiveCommand;

import org.eclipse.jgit.transport.TrackingRefUpdate;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.slf4j.Logger;

@@ -151,3 +154,8 @@ import org.slf4j.LoggerFactory;

Git git = new Git(repository);
FetchResult result = git.fetch().setRemote(mirror.getName()).setDryRun(testing).call();
CredentialsProvider creds = null;
URIish fetchUri = mirror.getURIs().get(0);
if (fetchUri.getUser() != null && fetchUri.getPass() != null) {
creds = new UsernamePasswordCredentialsProvider(fetchUri.getUser(), fetchUri.getPass());
}
FetchResult result = git.fetch().setCredentialsProvider(creds).setRemote(mirror.getName()).setDryRun(testing).call();
Collection<TrackingRefUpdate> refUpdates = result.getTrackingRefUpdates();

@@ -154,0 +162,0 @@ if (refUpdates.size() > 0) {

@@ -72,3 +72,4 @@ /*

@Override
protected String getBranch(String repository, HttpServletRequest request) {
String getBranch(String repository, String pathInfo)
{
return "gh-pages";

@@ -78,4 +79,4 @@ }

@Override
protected String getPath(String repository, String branch, HttpServletRequest request) {
String pi = request.getPathInfo().substring(1);
String getPath(String repository, String branch, String pi)
{
if (pi.equals(repository)) {

@@ -82,0 +83,0 @@ return "";

@@ -39,2 +39,3 @@ /*

import org.apache.tika.Tika;
import org.apache.wicket.protocol.http.WicketURLEncoder;
import org.eclipse.jgit.lib.FileMode;

@@ -73,2 +74,5 @@ import org.eclipse.jgit.lib.MutableObjectId;

// Forward slash character
static final char FSC = '!';
private static final long serialVersionUID = 1L;

@@ -104,7 +108,12 @@

}
if (repository.length() > 0 && repository.charAt(repository.length() - 1) == '/') {
repository = repository.substring(0, repository.length() - 1);
}
if (repository.length() > 0 && repository.charAt(0) == '/') {
repository = repository.substring(1);
}
char fsc = '!';
char c = GitblitContext.getManager(IRuntimeManager.class).getSettings().getChar(Keys.web.forwardSlashCharacter, '/');
if (c != '/') {
fsc = c;
char fsc = GitblitContext.getManager(IRuntimeManager.class).getSettings().getChar(Keys.web.forwardSlashCharacter, '/');
if (fsc == '/') {
fsc = FSC;
}

@@ -115,9 +124,27 @@ if (branch != null) {

if (path != null && path.length() > 0 && path.charAt(0) == '/') {
path = path.substring(1);
}
String encodedPath = path == null ? "" : path.replace('/', fsc);
return baseURL + Constants.RAW_PATH + repository + "/" + (branch == null ? "" : (branch + "/" + encodedPath));
String fullPath = repository + "/" + (branch == null ? "" : (branch + "/" + encodedPath));
return baseURL + Constants.RAW_PATH + WicketURLEncoder.FULL_PATH_INSTANCE.encode(fullPath);
}
protected String getBranch(String repository, HttpServletRequest request) {
String pi = request.getPathInfo();
String branch = pi.substring(pi.indexOf(repository) + repository.length() + 1);
/**
* Find and return the name of a branch from a given repository in a HTTP request path info.
* The branch name returned is transformed to the form in the repository, i.e. a transformation
* of the forward slash character in the URL is reversed.
*
* @param repository
* Path of repository, no leading slash, no trailing slash
* @param pathInfo
* The sanitised path info from a HTTP request, i.e. without the leading slash.
*
* @return The name of the branch from the path info, unescaped.
*/
String getBranch(String repository, String pathInfo)
{
if (pathInfo == null || pathInfo.isEmpty() || pathInfo.equals("/")) return "";
String branch = pathInfo.substring(pathInfo.indexOf(repository) + repository.length() + 1);
int fs = branch.indexOf('/');

@@ -131,14 +158,49 @@ if (fs > -1) {

protected String getPath(String repository, String branch, HttpServletRequest request) {
String base = repository + "/" + branch;
String pi = request.getPathInfo().substring(1);
if (pi.equals(base)) {
/**
* Find and return the path from a given repository and given branch in a HTTP request path info.
* The path string returned is transformed to the form in the repository, i.e. a transformation
* of the forward slash character in the URL is reversed.
*
* @param repository
* Path of repository, no leading slash, no trailing slash
* @param branch
* Branch name from the repository, i.e. with forward slash character, no leading slash, no trailing slash.
* @param pathInfo
* The sanitised path info from a HTTP request, i.e. without the leading slash.
*
* @return The file/folder path part from the path info, in unescaped form.
*/
String getPath(String repository, String branch, String pathInfo)
{
if (pathInfo == null || pathInfo.isEmpty() || pathInfo.equals("/")) return "";
// Make the branch look like in the URL, or else it won't match later in the `indexOf`.
char c = runtimeManager.getSettings().getChar(Keys.web.forwardSlashCharacter, '/');
char fsc = (c == '/') ? FSC : c;
String base = repository + "/" + Repository.shortenRefName(branch).replace('/', fsc);
// 'repository/' or 'repository/branch' or 'repository/branch/'
if (pathInfo.equals(base)) {
return "";
}
String path = pi.substring(pi.indexOf(base) + base.length() + 1);
// I have no idea why 'indexOf(base)' is used, which assumes something could come before 'base' in
// the pathInfo string. But since it is here, we handle it until we completly refactor the paths used
// in Gitblit to something sensible.
// 'leadin/repository/'
// 'leadin/repository/branch'
int pathStart = pathInfo.indexOf(base) + base.length();
// 'leadin/repository/branch/'
if (pathStart < pathInfo.length() && pathInfo.charAt(pathStart) == '/') pathStart++;
if (pathInfo.length() == pathStart) return "";
// 'leadin/repository/branch/path'
String path = pathInfo.substring(pathStart);
path = path.replace('!', '/').replace(c, '/');
// 'repository/branch/path/'
// 'leadin/repository/branch/path/'
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
char c = runtimeManager.getSettings().getChar(Keys.web.forwardSlashCharacter, '/');
return path.replace('!', '/').replace(c, '/');
return path;
}

@@ -196,3 +258,3 @@

// identify the branch
String branch = getBranch(repository, request);
String branch = getBranch(repository, path);
if (StringUtils.isEmpty(branch)) {

@@ -216,3 +278,3 @@ branch = r.getBranch();

// identify the requested path
String requestedPath = getPath(repository, branch, request);
String requestedPath = getPath(repository, branch, path);

@@ -219,0 +281,0 @@ // identify the commit

@@ -62,3 +62,7 @@ /*

public static boolean isToday(Date date, TimeZone timezone) {
Date now = new Date();
return isToday(date, timezone, new Date());
}
static boolean isToday(Date date, TimeZone timezone, Date now) {
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");

@@ -78,4 +82,9 @@ if (timezone != null) {

public static boolean isYesterday(Date date, TimeZone timezone) {
return isYesterday(date, timezone, new Date());
}
static boolean isYesterday(Date date, TimeZone timezone, Date now) {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.setTime(now);
cal.add(Calendar.DATE, -1);

@@ -162,3 +171,8 @@ SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");

public static int hoursAgo(Date date, boolean roundup) {
long diff = System.currentTimeMillis() - date.getTime();
return hoursAgo(date, System.currentTimeMillis(), roundup);
}
static int hoursAgo(Date date, long now, boolean roundup) {
long diff = now - date.getTime();
int hours = (int) (diff / ONEHOUR);

@@ -178,3 +192,7 @@ if (roundup && (diff % ONEHOUR) >= HALFHOUR) {

public static int daysAgo(Date date) {
long today = ONEDAY * (System.currentTimeMillis()/ONEDAY);
return daysAgo(date, System.currentTimeMillis());
}
static int daysAgo(Date date, long now) {
long today = ONEDAY * (now/ONEDAY);
long day = ONEDAY * (date.getTime()/ONEDAY);

@@ -186,2 +204,53 @@ long diff = today - day;

/**
* Return the difference in calendar days between a given timestamp and the date.
* Calendar days means that the difference is calculated between
* calendar days, not 24 hour increments.
*
* This means the result is dependent on the timezone. Only the local
* time's time zone is used, i.e. both time stamps are interpreted in
* the given time zone.
*
* E.g. if now is 10:00 on 20.10.2020 GMT and the date given is for
* either 6:00 or 20:00 on 18.10.2020 GMT then the result is two days
* in both cases.
*
*
* @param date
* Date in the past
* @param now
* Timestamp representing current time (used for unit tests)
* @return calendar days ago
*/
static int calendarDaysAgo(Date date, TimeZone timezone, long now) {
Calendar cal;
if (timezone == null) {
cal = Calendar.getInstance();
} else {
cal = Calendar.getInstance(timezone);
}
cal.setTimeInMillis(now);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.HOUR_OF_DAY, 12);
long today = cal.getTime().getTime();
cal.clear();
cal.setTime(date);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.HOUR_OF_DAY, 12);
long day = cal.getTime().getTime();
long diff = today - day;
int days = (int) (diff / ONEDAY);
return days;
}
public String today() {

@@ -225,4 +294,10 @@ return translate("gb.time.today", "today");

private String timeAgo(Date date, boolean css) {
if (isToday(date, timezone) || isYesterday(date, timezone)) {
int mins = minutesAgo(date, true);
return timeAgo(date, css, System.currentTimeMillis());
}
String timeAgo(Date date, boolean css, long now) {
Date dNow = new Date(now);
if (isToday(date, timezone, dNow) || isYesterday(date, timezone, dNow)) {
int mins = minutesAgo(date, now, true);
if (mins >= 120) {

@@ -232,3 +307,3 @@ if (css) {

}
int hours = hoursAgo(date, true);
int hours = hoursAgo(date, now, true);
if (hours > 23) {

@@ -248,3 +323,3 @@ return yesterday();

} else {
int days = daysAgo(date);
int days = calendarDaysAgo(date, timezone, now);
if (css) {

@@ -251,0 +326,0 @@ if (days <= 7) {

@@ -246,3 +246,2 @@

gb.query=dotaz
gb.ticketState=Stav \u00fakolu
gb.to=do

@@ -430,2 +429,3 @@ gb.newTicket=nov\u00fd \u00fakol

gb.ticketsWelcome=M\u016f\u017eete pou\u017e\u00edt \u00fakoly k organizaci va\u0161eho seznamu \u00fakol\u016f, diskutovat chyby a spolupracovat na sad\u00e1ch zm\u011bn.
gb.sshKeyComment=Koment\u00e1\u0159
gb.sshKeyCommentDescription=Vlo\u017ete voliteln\u00fd koment\u00e1\u0159. Pokud bude pr\u00e1zdn\u00fd, bude automaticky vyta\u017een z dat kl\u00ed\u010de.

@@ -664,3 +664,3 @@ gb.feed=kan\u00e1l

gb.responsible=zodpov\u011bdn\u00fd
gb.accessPermissionsDescription=omezit p\u0159\u00edstup na u\u017eivatel\u00e9 a t\u00fdmy\n
gb.accessPermissionsDescription=omezit p\u0159\u00edstup na u\u017eivatel\u00e9 a t\u00fdmy
gb.namedPushPolicy=Omezit Push (Pojmenovan\u00fd)

@@ -792,1 +792,4 @@ gb.viewPolicy=Omezit prohl\u00ed\u017een\u00ed, klonov\u00e1n\u00ed a Push

palette.selected=Vybran\u00ed
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = \u010de\u0161tina

@@ -143,3 +143,3 @@ gb.repository = Repository

gb.myUrlDescription = Die \u00f6ffentlich zugreifbare URL f\u00fcr Ihre Gitblit-Instanz
gb.destinationUrl = Senden an
gb.destinationUrl = Senden an
gb.destinationUrlDescription = Die URL der Gitblit-Instanz, an welche die Anfrage gestellt werden soll

@@ -174,3 +174,2 @@ gb.users = Benutzer

gb.since = seit
gb.status = Status
gb.bootDate = Boot-Zeitpunkt

@@ -319,3 +318,3 @@ gb.servletContainer = Servlet container

gb.allowAuthenticatedDescription = Allen authentifizierten Benutzern RW+ Recht gew\u00e4hren
gb.allownameddescription = Benutzern und Teams feingranulare Rechte gew\u00e4hren
gb.allowNamedDescription = Benutzern und Teams feingranulare Rechte gew\u00e4hren
gb.markdownFailure = Markdown Inhalt konnte nicht geparst werden!

@@ -438,3 +437,3 @@ gb.clearCache = Cache leeren

gb.warning = Warnung
gb.jcwWarning = Ihrem Java Runtime Environment fehlen die \"JCE Unlimited Strength Jurisdiction Policy\" Dateien.\nDies schr\u00e4nkt die L\u00e4nge der Passw\u00f6rter, die Sie zum Verschl\u00fcsseln Ihrer Keystores verwenden k\u00f6nnen, auf 7 Zeichen ein.\nDiese Policy-Dateien sind ein optionaler Download von Oracle.\n\nM\u00f6chten Sie fortfahren und die Zertifikat-Infrastruktur trotzdem erstellen?\n\nWenn Sie mit Nein antworten, wird Ihr Browser die Oracle Download-Seite \u00f6ffnen, auf welcher Sie die Policy-Dateien herunterladen k\u00f6nnen.
gb.jceWarning = Ihrem Java Runtime Environment fehlen die \"JCE Unlimited Strength Jurisdiction Policy\" Dateien.\nDies schr\u00e4nkt die L\u00e4nge der Passw\u00f6rter, die Sie zum Verschl\u00fcsseln Ihrer Keystores verwenden k\u00f6nnen, auf 7 Zeichen ein.\nDiese Policy-Dateien sind ein optionaler Download von Oracle.\n\nM\u00f6chten Sie fortfahren und die Zertifikat-Infrastruktur trotzdem erstellen?\n\nWenn Sie mit Nein antworten, wird Ihr Browser die Oracle Download-Seite \u00f6ffnen, auf welcher Sie die Policy-Dateien herunterladen k\u00f6nnen.
gb.maxActivityCommits = Maximale Commits Aktivit\u00e4t

@@ -529,3 +528,3 @@ gb.maxActivityCommitsDescription = Maximale Anzahl von Commits die auf der Aktivit\u00e4tsseite dargestellt werden

gb.toBranch = nach {0}
gb.createdBy = angelegt durch
gb.createdBy = angelegt durch
gb.oneParticipant = {0} Teilnehmer

@@ -600,3 +599,3 @@ gb.nParticipants = {0} Teilnehmer

gb.title = \u00dcberschrift
gb.changedStatus = hat Status ge\u00e4ndert
gb.changedStatus = hat Status ge\u00e4ndert
gb.discussion = Diskussion

@@ -729,3 +728,3 @@ gb.updated = aktualisiert

gb.originDescription = Die URL, von welcher dieses Repository geklont wurde.
gb.gc = GC
gb.gc = GC
gb.garbageCollection = Garbage Collection

@@ -747,5 +746,4 @@ gb.garbageCollectionDescription = Die Garbage Collection b\u00fcndelt freie Objekte, welche von Clients gepusht wurden und entfernt nicht mehr referenzierte Objekte aus dem Repository.

gb.key = Key
gb.comment = Kommentar
gb.sshKeyComment = Kommentar
gb.sshKeyCommentDescription = Geben Sie optional einen Kommentar ein. Falls Sie dies nicht tun, wird der Kommentar aus dem Key extrahiert.
gb.permission = Berechtigung

@@ -764,2 +762,5 @@ gb.sshKeyPermissionDescription = Geben Sie die Zugriffberechtigung f\u00fcr den SSH Key an

gb.blinkComparator = Blinkkomparator
gb.imgdiffSubtract = Pixeldifferenz (schwarz = identisch)
gb.imgdiffSubtract = Pixeldifferenz (schwarz = identisch)
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = Deutsch

@@ -21,3 +21,3 @@ gb.repository = Repositorio

gb.ticketOpenDate = Fecha de apertura
gb.ticketState = Estado
gb.ticketStatus = Estado
gb.ticketComments = Comentarios

@@ -62,8 +62,8 @@ gb.view = Ver

gb.markdown = Markdown
gb.changedFiles = Archivos cambiados
gb.changedFiles = Archivos cambiados
gb.filesAdded = {0} Archivos a\u00F1adidos
gb.filesModified = {0} Archivos modificados
gb.filesDeleted = {0} Archivos eliminados
gb.filesCopied = {0} Archivos copiados
gb.filesRenamed = {0} Archivos renombrados
gb.filesModified = {0} Archivos modificados
gb.filesDeleted = {0} Archivos eliminados
gb.filesCopied = {0} Archivos copiados
gb.filesRenamed = {0} Archivos renombrados
gb.missingUsername = Usuario omitido

@@ -175,3 +175,2 @@ gb.edit = Editar

gb.since = Desde
gb.status = Estado
gb.bootDate = Fecha de inicio

@@ -244,3 +243,3 @@ gb.servletContainer = Contenedor ServLet

gb.pleaseSetRepositoryName = \u00A1Por favor introduce un nombre para el repositorio!
gb.illegalLeadingSlash = Referencias a la carpeta ra\i00EDz (/) estu00E1n prohibidas.
gb.illegalLeadingSlash = Referencias a la carpeta ra\u00EDz (/) estu00E1n prohibidas.
gb.illegalRelativeSlash = Referencias relativas a la carpeta (../) est\u00E1n prohibidas.

@@ -261,4 +260,4 @@ gb.illegalCharacterRepositoryName = \u00A1Caracter ilegal ''{0}'' en el nombre del repositorio!

gb.branchStats = {0} consigna(s) y {1} etiqueta(s) en {2}
gb.repositoryNotSpecified = /u00A1Repositorio no especificado!
gb.repositoryNotSpecifiedFor = /u00A1Repositorio no especificado para {0}!
gb.repositoryNotSpecified = \u00A1Repositorio no especificado!
gb.repositoryNotSpecifiedFor = \u00A1Repositorio no especificado para {0}!
gb.canNotLoadRepository = No se puede cargar el repositorio

@@ -280,5 +279,5 @@ gb.commitIsNull = La consigna es nula

gb.noFederation = Lo siento, {0} no est\u00E1 configurado para Federar con ninguna instancia de GitBlit.
gb.proposalFailed = /u00A1Lo siento, {0} no ha recibido ning\u00FAn dato de propuesta!
gb.proposalError = /u00A1Lo siento, {0} informa de que ha ocurrido un error inesperado!
gb.failedToSendProposal = /u00A1Fallo al enviar la propuesta!
gb.proposalFailed = \u00A1Lo siento, {0} no ha recibido ning\u00FAn dato de propuesta!
gb.proposalError = \u00A1Lo siento, {0} informa de que ha ocurrido un error inesperado!
gb.failedToSendProposal = \u00A1Fallo al enviar la propuesta!
gb.userServiceDoesNotPermitAddUser = \u00A1{0} no permite a\u00F1adir una cuenta de usuario!

@@ -421,3 +420,3 @@ gb.userServiceDoesNotPermitPasswordChanges = \u00A1{0} no permite cambio de contrase\u00F1a!

gb.superseded = Sustituida
gb.cessationOfOperation = Cese de operaci\u00F3n
gb.cessationOfOperation = Cese de operaci\u00F3n
gb.privilegeWithdrawn = Privilegios retirados

@@ -431,3 +430,3 @@ gb.time.inMinutes = en {0} mints

gb.newCertificateDefaults = Nuevo certificado predeterminado
gb.duration = Duraci\u00F3n
gb.duration = Duraci\u00F3n
gb.certificateRevoked = El cretificado {0,n\u00FAmero,0} ha sido revocado

@@ -452,3 +451,3 @@ gb.clientCertificateGenerated = Nuevo certificado de cliente generado correctamente para {0}

gb.siteName = Nombre del sitio
gb.siteNameDescription = Nombre corto y descriptivo de tu servidor
gb.siteNameDescription = Nombre corto y descriptivo de tu servidor
gb.excludeFromActivity = Excluir de la p\u00E1gina de actividad

@@ -459,5 +458,5 @@ gb.isSparkleshared = compartido mediante Sparkleshared

gb.closeBrowser = Porfavor cierre el navegador para terminar correctamente la sesi\u00F3n.
b.doesNotExistInTree = {0} no existe en el \u00E1rbol {1}
gb.doesNotExistInTree = {0} no existe en el \u00E1rbol {1}
gb.enableIncrementalPushTags = Etiquetar incrementalmente al empujar
gb.useIncrementalPushTagsDescription = Al empujar, etiquetar autom\u00E1ticamente cada punta de la rama con un n\u00FAmero incremental de revisi\u00F3n
gb.useIncrementalPushTagsDescription = Al empujar, etiquetar autom\u00E1ticamente cada punta de la rama con un n\u00FAmero incremental de revisi\u00F3n
gb.incrementalPushTagMessage = Auto-etiquetado [{0}] rama al empujar

@@ -519,3 +518,3 @@ gb.externalPermissions = {0} los permisos de acceso son mantenidos externamente

gb.diffStat = {0} inserciones | {1} supresiones
b.home = Home
gb.home = Home
gb.isMirror = Este repositorio es un espejo

@@ -657,3 +656,3 @@ gb.mirrorOf = Espejo de {0}

gb.reviews = revisiones
gb.veto = veto
gb.veto = veto
gb.needsImprovement = necesita mejorar

@@ -685,2 +684,6 @@ gb.looksGood = parece bueno

gb.ticketIsClosed = Este ticket est\u00E1 cerrado.
gb.mergeToDescription = Rama de integraciu00F3n predeterminada para combinar ticket y parches
gb.mergeToDescription = Rama de integraciu00F3n predeterminada para combinar ticket y parches
gb.sshKeyComment = Comentar
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = Espa\u00f1ol

@@ -52,3 +52,3 @@ gb.repository = d\u00e9p\u00f4t

gb.search = recherche
gb.searchForAuthor = Recherche des livraisons dont l'auteur est
gb.searchForAuthor = Recherche des livraisons dont l'auteur est
gb.searchForCommitter = Recherche des livraisons livr\u00e9es par

@@ -112,3 +112,3 @@ gb.addition = ajout

gb.excludeFromFederationDescription = emp\u00eacher les instances Gitblit f\u00e9d\u00e9r\u00e9e de "puller" ce compte
gb.tokens = jettons de la f\u00e9d\u00e9ration
gb.tokens = jettons de la f\u00e9d\u00e9ration
gb.tokenAllDescription = tous les d\u00e9p\u00f4ts, utilisateurs & param\u00e8tres

@@ -175,3 +175,2 @@ gb.tokenUnrDescription = tous les d\u00e9p\u00f4ts & utilisateurs

gb.since = depuis
gb.status = \u00e9tat
gb.bootDate = date de d\u00e9marrage

@@ -444,3 +443,3 @@ gb.servletContainer = conteneur de servlet

gb.serveCertificate = servir https avec ce certificat
gb.sslCertificateGeneratedRestart = Un nouveau certificat serveur SSL a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9 avec succ\u00e8s pour {0}.\Gitblit doit \u00eatre red\u00e9marrer pour prendre en compte le nouveau certificat.\n\nSi vous utilisez l'option de demarrage '--alias', v\u00e9rifiez qu'elle est d\u00e9finie comme suit : ''--alias {0}''.
gb.sslCertificateGeneratedRestart = Un nouveau certificat serveur SSL a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9 avec succ\u00e8s pour {0}.\nGitblit doit \u00eatre red\u00e9marrer pour prendre en compte le nouveau certificat.\n\nSi vous utilisez l'option de demarrage '--alias', v\u00e9rifiez qu'elle est d\u00e9finie comme suit : ''--alias {0}''.
gb.validity = validit\u00e9

@@ -650,3 +649,3 @@ gb.siteName = nom du site

gb.reviews = v\u00e9rifications
gb.veto = v\u00e9to
gb.veto = v\u00e9to
gb.needsImprovement = demande am\u00e9lioration

@@ -690,2 +689,6 @@ gb.looksGood = semble bon

gb.blinkComparator = Comparateur \u00e0 clignotement
gb.imgdiffSubtract = Diff\u00e9rence (noir = identique)
gb.imgdiffSubtract = Diff\u00e9rence (noir = identique)
gb.sshKeyComment = Commentaire
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = fran\u00e7ais

@@ -173,3 +173,2 @@ gb.repository = repository

gb.since = da
gb.status = stato
gb.bootDate = data di avvio del server

@@ -328,3 +327,3 @@ gb.servletContainer = servlet container

gb.forkRepository = crea una ramificazione {0}?
gb.repositoryForked = ramificazione creata per {0}
gb.repositoryForked = ramificazione creata per {0}
gb.repositoryForkFailed= ramificazione fallita

@@ -602,3 +601,3 @@ gb.personalRepositories = repository personali

gb.proposePatchsetNote = Sei il benvenuto nel proporre una patch per questo ticket.
gb.proposeInstructions = Per iniziare, crea una patch e fanne l'upload con Git. Gitblit colleger� la tua patch a questo ticket per id.
gb.proposeInstructions = Per iniziare, crea una patch e fanne l'upload con Git. Gitblit colleger� la tua patch a questo ticket per id.
gb.proposeWith = Proponi una patch con {0}

@@ -649,3 +648,3 @@ gb.revisionHistory = cronologia revisioni

gb.reviews = revisioni
gb.veto = veto
gb.veto = veto
gb.needsImprovement = da migliorare

@@ -727,3 +726,3 @@ gb.looksGood = sembra buona

gb.originDescription = URL da cui questo repository � stato clonato
gb.gc = GC
gb.gc = GC
gb.garbageCollection = Garbage Collection

@@ -745,5 +744,4 @@ gb.garbageCollectionDescription = Lo spazzino (GC) comprimer� gli oggetti inviati da client Git and rimuover� dal repository oggetti non pi� referenziati.

gb.key = Chiave
gb.comment = Commento
gb.sshKeyComment = Commento
gb.sshKeyCommentDescription = Aggiungi opzionalmente un commento. Se vuoto, il commento sar� estratto dalla chiave stessa.
gb.permission = Permesso
gb.sshKeyPermissionDescription = Definisci il il livello di accesso per la chiave SSH

@@ -753,1 +751,3 @@ gb.transportPreference = Preferenze di trasporto

# This last property for unit tests to test successful loading of the resource file
gb.loadLang = Italiano

@@ -61,3 +61,3 @@ gb.repository = \uC800\uC7A5\uC18C

gb.markdown = \uB9C8\uD06C\uB2E4\uC6B4
gb.changedFiles = \uD30C\uC77C \uBCC0\uACBD\uB428
gb.changedFiles = \uD30C\uC77C \uBCC0\uACBD\uB428
gb.filesAdded = {0}\uAC1C \uD30C\uC77C \uCD94\uAC00\uB428

@@ -174,3 +174,2 @@ gb.filesModified = {0}\uAC1C \uD30C\uC77C \uBCC0\uACBD\uB428

gb.since = since
gb.status = \uC0C1\uD0DC
gb.bootDate = \uBD80\uD305 \uC77C\uC790

@@ -475,3 +474,3 @@ gb.servletContainer = \uC11C\uBE14\uB9BF \uCEE8\uD14C\uC774\uB108

gb.byNAuthors = {0} \uBA85\uC758 \uC791\uC131\uC790
gb.byOneAuthor = {0} \uC5D0 \uC758\uD574
gb.byOneAuthor = {0} \uC5D0 \uC758\uD574
gb.viewComparison = {0} \uCEE4\uBC0B\uC758 \uBE44\uAD50 \uBCF4\uAE30 \u00BB

@@ -729,3 +728,3 @@ gb.nMoreCommits = {0} \uAC1C \uB354 \u00BB

gb.originDescription = \uC774 \uC800\uC7A5\uC18C\uAC00 \uD074\uB860\uB41C \uACF3\uC758 url
gb.gc = GC
gb.gc = GC
gb.garbageCollection = \uAC00\uBE44\uC9C0 \uCEEC\uB809\uC158

@@ -737,3 +736,3 @@ gb.garbageCollectionDescription = \uAC00\uBE44\uC9C0 \uCEEC\uB809\uD130\uB294 \uD074\uB77C\uC774\uC5B8\uD2B8\uC5D0\uC11C \uD478\uC2DC\uD55C \uB290\uC2A8\uD55C \uC624\uBE0C\uC81D\uD2B8\uB97C \uD328\uD0B9\uD558\uACE0, \uC800\uC7A5\uC18C\uC5D0\uC11C \uCC38\uC870\uD558\uC9C0 \uC54A\uB294 \uC624\uBE0C\uC81D\uD2B8\uB97C \uC0AD\uC81C\uD569\uB2C8\uB2E4.

gb.accountPreferencesDescription = \uACC4\uC815 \uC124\uC815\uC744 \uC9C0\uC815\uD569\uB2C8\uB2E4.
gb.languagePreference = \uC5B8\uC5B4 \uC124\uC815
gb.languagePreference = \uC5B8\uC5B4 \uC124\uC815
gb.languagePreferenceDescription = \uC120\uD638\uD558\uB294 \uC5B8\uC5B4\uB97C \uC120\uD0DD\uD558\uC138\uC694.

@@ -745,8 +744,7 @@ gb.emailMeOnMyTicketChanges = \uB0B4 \uD2F0\uCF13\uC774 \uBCC0\uACBD\uB418\uBA74 \uC774\uBA54\uC77C\uB85C \uC54C\uB9BC

gb.sshKeys = SSH \uD0A4
gb.sshKeysDescription = SSH \uACF5\uAC1C\uD0A4 \uC778\uC99D\uC740 \uD328\uC2A4\uC6CC\uB4DC \uC778\uC99D\uC744 \uB300\uCCB4\uD558\uB294 \uC548\uC804\uD55C \uB300\uC548\uC785\uB2C8\uB2E4.
gb.sshKeysDescription = SSH \uACF5\uAC1C\uD0A4 \uC778\uC99D\uC740 \uD328\uC2A4\uC6CC\uB4DC \uC778\uC99D\uC744 \uB300\uCCB4\uD558\uB294 \uC548\uC804\uD55C \uB300\uC548\uC785\uB2C8\uB2E4.
gb.addSshKey = SSH \uD0A4 \uCD94\uAC00
gb.key = \uD0A4
gb.comment = \uC124\uBA85
gb.sshKeyComment = \uC124\uBA85
gb.sshKeyCommentDescription = \uC0AC\uC6A9\uC790 \uC120\uD0DD\uC778 \uC124\uBA85\uC744 \uCD94\uAC00\uD558\uC138\uC694. \uBE44\uC6CC \uB450\uBA74 \uD0A4 \uB370\uC774\uD130\uC5D0\uC11C \uCD94\uCD9C\uD558\uC5EC \uCC44\uC6CC\uC9D1\uB2C8\uB2E4.
gb.permission = \uAD8C\uD55C
gb.sshKeyPermissionDescription = SSH \uD0A4\uC758 \uC811\uC18D \uAD8C\uD55C\uC744 \uC9C0\uC815\uD558\uC138\uC694.

@@ -793,1 +791,5 @@ gb.transportPreference = \uC804\uC1A1 \uC124\uC815

gb.referencedByTicket = \uD2F0\uCF13\uC5D0 \uCC38\uC870\uB428.
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = \ud55c\uad6d\uc5b4

@@ -21,3 +21,3 @@ gb.repository = repositorie

gb.ticketOpenDate = open datum
gb.ticketState = status
gb.ticketStatus = status
gb.ticketComments = commentaar

@@ -174,3 +174,2 @@ gb.view = view

gb.since = sinds
gb.status = status
gb.bootDate = boot datum

@@ -215,3 +214,3 @@ gb.servletContainer = servlet container

gb.accessPermissionsForUserDescription = stel teamlidmaatschappen in of geef toegang tot specifieke besloten repositories
gb.accessPermissionsForTeamDescription = stel teamlidmaatschappen in en geef toegang tot specifieke besloten repositories
gb.accessPermissionsForTeamDescription = stel teamlidmaatschappen in en geef toegang tot specifieke besloten repositories
gb.federationRepositoryDescription = deel deze repositorie met andere Gitblit servers

@@ -268,3 +267,3 @@ gb.hookScriptsDescription = run Groovy scripts bij pushes naar deze Gitblit server

gb.invalidUsernameOrPassword = Onjuiste gebruikersnaam of wachtwoord!
gb.OneProposalToReview = Er is 1 federatie voorstel dat wacht op review.
gb.OneProposalToReview = Er is 1 federatie voorstel dat wacht op review.
gb.nFederationProposalsToReview = Er zijn {0} federatie verzoeken die wachten op review.

@@ -299,3 +298,3 @@ gb.couldNotFindTag = Kon tag {0} niet vinden

gb.repositoryDeleted = Repositorie ''{0}'' verwijderd.
gb.repositoryDeleteFailed = Verwijdering van repositorie ''{0}'' mislukt!
gb.repositoryDeleteFailed = Verwijdering van repositorie ''{0}'' mislukt!
gb.deleteUser = Verwijder gebruiker \"{0}\"?

@@ -616,3 +615,3 @@ gb.userDeleted = Gebruiker ''{0}'' verwijderd.

gb.checkoutViaCommandLineNote = U kunt deze wijzigingen uitchecken en lokaal testen vanuit uw eigen kopie van deze repositorie.
gb.checkoutStep1 = Dowbload the actuele patchset \u2014 run deze vanuit uw eigen projectdirectorie
gb.checkoutStep1 = Download the actuele patchset \u2014 run deze vanuit uw eigen projectdirectorie
gb.checkoutStep2 = Check de patchset uit naar een nieuwe branch en review hem

@@ -652,3 +651,3 @@ gb.mergingViaCommandLine = Mergen via commandline

gb.reviews = reviews
gb.veto = veto
gb.veto = veto
gb.needsImprovement = kan beter

@@ -730,3 +729,3 @@ gb.looksGood = ziet er goed uit

gb.originDescription = De url vanaf welke deze repositorie was gecloned.
gb.gc = GC
gb.gc = GC
gb.garbageCollection = Garbage Collection

@@ -748,7 +747,10 @@ gb.garbageCollectionDescription = De garbage collector zal losse objecten die gepushed zijn van clients samenvoegen en zal ongereferentieerde objecten uit de repository verwijderen.

gb.key = Sleutel
gb.comment = Opmerking
gb.sshKeyComment = Opmerking
gb.sshKeyCommentDescription = Voeg een optionele opmerking toe. Indien leeg zal de opmerking uit de sleutelgegevens worden gehaald.
gb.permission = Permissie
gb.sshKeyPermissionDescription = Specificeer de toegangsrechten voor de SSH sleutel
gb.transportPreference = Transportvoorkeuren
gb.transportPreferenceDescription = Stel de transportmethode in die u wenst voor het clonen
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = Nederlands

@@ -52,4 +52,4 @@ gb.repository = repository

gb.search = s\u00F8k
gb.searchForAuthor = S\u00F8k etter commits skrever av
gb.searchForCommitter = S\u00F8k etter commits committet av
gb.searchForAuthor = S\u00F8k etter commits skrever av
gb.searchForCommitter = S\u00F8k etter commits committet av
gb.addition = lagt til

@@ -92,3 +92,3 @@ gb.modification = endring

gb.canAdminDescription = kan administere Gitblit server
gb.permittedUsers = tillatte brukere
gb.permittedUsers = tillatte brukere
gb.isFrozen = er frosset

@@ -100,3 +100,3 @@ gb.isFrozenDescription = avvis push operasjoner

gb.nameDescription = bruk '/' for \u00e5 gruppere repositorier. F.eks libraries/mycoollib.git
gb.ownerDescription = eieren kan redigere repository-innstillinge
gb.ownerDescription = eieren kan redigere repository-innstillinge
gb.blob = blob

@@ -142,3 +142,3 @@ gb.commitActivityTrend = aktivitetstrend for commits

gb.federationRegistration = federeringsregistrering
gb.federationResults = resultat av federerings pull
gb.federationResults = resultat av federerings pull
gb.federationSets = federeringssett

@@ -163,4 +163,4 @@ gb.message = melding

gb.downloading = laster ned
gb.loading = laster
gb.starting = starter
gb.loading = laster
gb.starting = starter
gb.general = generelt

@@ -178,3 +178,2 @@ gb.settings = innstillinger

gb.since = siden
gb.status = status
gb.bootDate = oppstartstidspunkt

@@ -202,3 +201,3 @@ gb.servletContainer = servlet container

gb.teamName = teamnavn
gb.teamMembers = teammedlemmer
gb.teamMembers = teammedlemmer
gb.teamMemberships = teammedlemskap

@@ -217,7 +216,7 @@ gb.newTeam = nytt team

gb.filters = filtre
gb.generalDescription = vanlige innstillinger
gb.generalDescription = vanlige innstillinger
gb.accessPermissionsDescription = begrens tilgang vha brukere og team
gb.accessPermissionsForUserDescription = sett teammedlemskap eller gi tilgang til spesifikke repositorier
gb.accessPermissionsForTeamDescription = sett teammedlemskap eller gi tilgang til spesifikke repositorier
gb.federationRepositoryDescription = del dette repositoriett med andre Gitblit servere
gb.federationRepositoryDescription = del dette repositoriett med andre Gitblit servere
gb.hookScriptsDescription = kj\u00F8r Groovy scripts ved pushes til denne Gitblit serveren

@@ -236,3 +235,3 @@ gb.reset = reset

gb.indexedBranches = indekserte brancher
gb.indexedBranchesDescription = velg branchene som skal inkluderes i din Lucene indeks.
gb.indexedBranchesDescription = velg branchene som skal inkluderes i din Lucene indeks.
gb.noIndexedRepositoriesWarning = ingen av dine repositorier er satt opp med Lucene indeksering

@@ -250,3 +249,3 @@ gb.undefinedQueryWarning = sp\u00F8rringen er udefinert

gb.pleaseSetRepositoryName = Vennligst sett repositorynavnet!
gb.illegalLeadingSlash = Katalognavn kan ikke begynne med '/'
gb.illegalLeadingSlash = Katalognavn kan ikke begynne med '/'
gb.illegalRelativeSlash = Relative katalognavn (../) kan ikke benyttes.

@@ -276,3 +275,3 @@ gb.illegalCharacterRepositoryName = Ugyldig tegn ''{0}'' i repositorynavnet!

gb.OneProposalToReview = 1 federeringsforslag venter p\u00e5 behandling.
gb.nFederationProposalsToReview = {0} federeingsforslag venter p\u00e5 behandling.
gb.nFederationProposalsToReview = {0} federeingsforslag venter p\u00e5 behandling.
gb.couldNotFindTag = Fant ikke tag {0}

@@ -347,3 +346,3 @@ gb.couldNotCreateFederationProposal = Kunne ikke opprette federeringsforslag!

gb.myFork = se min fork
gb.forksProhibited = forkig er ikke tillattt
gb.forksProhibited = forkig er ikke tillattt
gb.forksProhibitedWarning = dette repositoriet tillater ikke forking

@@ -356,6 +355,6 @@ gb.noForks = {0} har ingen forks

gb.canCreate = kan opprette
gb.canCreateDescription = kan opprette personlige repositorier
gb.canCreateDescription = kan opprette personlige repositorier
gb.illegalPersonalRepositoryLocation = ditt personlige repository m\u00e5 v\u00e6re plassert p\u00e5 \"{0}\"
gb.verifyCommitter = verifiser committer
gb.verifyCommitterDescription = krev at committer identitet matcher pushing Gitblit brukerkonto
gb.verifyCommitterDescription = krev at committer identitet matcher pushing Gitblit brukerkonto
gb.verifyCommitterNote = alle merger krever "--no-ff" for \u00e5 beolde kjent committer identitet

@@ -366,3 +365,3 @@ gb.repositoryPermissions = repository tilganger

gb.add = legg til
gb.noPermission = SLETT DENNE TILGANGEN
gb.noPermission = SLETT DENNE TILGANGEN
gb.excludePermission = {0} (ekskluder)

@@ -375,3 +374,3 @@ gb.viewPermission = {0} (vis)

gb.rewindPermission = {0} (push, ref creation+deletion+rewind)
gb.permission = tilgang
gb.permission = Tilgang
gb.regexPermission = denne tilgangen er gitt av regul\u00e6ruttrykket \"{0}\"

@@ -417,3 +416,3 @@ gb.accessDenied = ingen tilgang

gb.issuer = utsteder
gb.validFrom = gyldig fra
gb.validFrom = gyldig fra
gb.validUntil = gyldig til

@@ -425,3 +424,3 @@ gb.publicKey = public key

gb.reason = begrunnelse
gb.revokeCertificateReason = Vennligst angi en grunn for tilbakekalling av sertifikatet.
gb.revokeCertificateReason = Vennligst angi en grunn for tilbakekalling av sertifikatet.
gb.unspecified = uspesifisert

@@ -433,3 +432,3 @@ gb.keyCompromise = n\u00F8kkelen er komprommitert

gb.cessationOfOperation = opph\u00F8rt
gb.privilegeWithdrawn = privileget er trukket tilbake
gb.privilegeWithdrawn = privileget er trukket tilbake
gb.time.inMinutes = om {0} minutter

@@ -467,3 +466,3 @@ gb.time.inHours = om {0} timer

gb.sessionEnded = Sesjonen har blitt lukket
gb.closeBrowser = Vennligst lukk nettleseren for \u00e5 avslutte sesjonen fullstendig.
gb.closeBrowser = Vennligst lukk nettleseren for \u00e5 avslutte sesjonen fullstendig.
gb.doesNotExistInTree = {0} finnes ikke i treet {1}

@@ -473,3 +472,3 @@ gb.enableIncrementalPushTags = sl\u00e5 p\u00e5 inkrementelle push tags

gb.incrementalPushTagMessage = Auto-tagget [{0}] branch ved push
gb.externalPermissions = {0} tilgangsrettigheter blir vedlikeholdt eksternt.
gb.externalPermissions = {0} tilgangsrettigheter blir vedlikeholdt eksternt.
gb.viewAccess = Du har hverken lese- eller skrivetilgang til Gitblit.

@@ -524,3 +523,3 @@ gb.overview = oversikt

gb.todaysActivityStats = i dag / {1} commits av {2} forfattere
gb.todaysActivityNone = i dag / ingen
gb.todaysActivityNone = i dag / ingen
gb.noActivityToday = det har ikke v\u00e6rt noen aktivitet i dag

@@ -534,3 +533,3 @@ gb.anonymousUser= anonym

gb.mirrorWarning = dette repositoriet er et speil, og kan ikke pushes til
gb.docsWelcome1 = Du kan bruke dokumentasjon til \u00e5 dokumentrere ditt repository
gb.docsWelcome1 = Du kan bruke dokumentasjon til \u00e5 dokumentrere ditt repository
gb.docsWelcome2 = Commit en README.md eller en HOME.md fil for \u00e5 komme i gang

@@ -611,3 +610,3 @@ gb.createReadme = lag en README

gb.searchTickets = s\u00F8k tickets
gb.new = ny
gb.new = ny
gb.newTicket = ny ticket

@@ -635,3 +634,3 @@ gb.editTicket = endre ticket

gb.checkoutStep1 = Hent det gjeldende patchsettet \u2014 kj\u00F8r dette fra din prosjekt-katalog
gb.checkoutStep2 = Checkout patchsettet til en ny branch og g\u00e5 igjennom koden
gb.checkoutStep2 = Checkout patchsettet til en ny branch og g\u00e5 igjennom koden
gb.mergingViaCommandLine = Merging vha kommandolinjen

@@ -670,3 +669,3 @@ gb.mergingViaCommandLineNote = Hvis du ikke \u00F8nsker \u00e5 bruke merge-knappen, eller hvis en automatisk merge ikke kan bli utf\u00F8rt, kan du gj\u00F8re en manuell merge p\u00e5 kommandolinjen.

gb.reviews = gjennomganger
gb.veto = veto
gb.veto = veto
gb.needsImprovement = m\u00e5 forbedres

@@ -722,9 +721,9 @@ gb.looksGood = ser bra ut

gb.namedPushPolicy = Begrens push (navngitt)
gb.namedPushPolicyDescription = Alle kan se og klone repositoriet. Du bestemmer hvem som kan pushe.
gb.namedPushPolicyDescription = Alle kan se og klone repositoriet. Du bestemmer hvem som kan pushe.
gb.clonePolicy = Begrens Clone og Push
gb.clonePolicyDescription = Alle kan se dette repositoriet. Du bestemmer hvem som kan clone og pushe.
gb.viewPolicy = Begrense View, Clone og Push
gb.viewPolicyDescription = Du bestemmer hvem som kan se, clone og pushe til dette repositoriet.
gb.viewPolicyDescription = Du bestemmer hvem som kan se, clone og pushe til dette repositoriet.
gb.initialCommit = F\u00F8rste commit
gb.initialCommitDescription = Dette vil la deg kunne <code>git clone</code> repositoriet med en gang. Hopp over dette skrittet hvis du allerede har kj\u0F8rt if <code>git init</code> lokalt.
gb.initialCommitDescription = Dette vil la deg kunne <code>git clone</code> repositoriet med en gang. Hopp over dette skrittet hvis du allerede har kj\u00F8rt if <code>git init</code> lokalt.
gb.initWithReadme = Inkluder en README

@@ -749,3 +748,3 @@ gb.initWithReadmeDescription = Dette vil generere en enkel README-fil i ditt repository.

gb.originDescription = URL'en som dette repositoriet ble klonet fra.
gb.gc = GC
gb.gc = GC
gb.garbageCollection = Garbage Collection

@@ -767,7 +766,9 @@ gb.garbageCollectionDescription = Garbage collectoren vil pakke sammen l\u00F8se objekter pushet fra klientene og fjerne objekter det ikke refereres til fra minnet.

gb.key = N\u00F8kkel
gb.comment = Kommentar
gb.sshKeyComment = Kommentar
gb.sshKeyCommentDescription = Angi en valgfri kommentar. Kommentaren vil bli ekstrahert fra n\u00F8kkeldataene hvis blank
gb.permission = Tilgang
gb.sshKeyPermissionDescription = Angi tilgangsrettinghet for SSH n\u00F8kkelen
gb.transportPreference = Foretrukket transport
gb.transportPreferenceDescription = Sett transportmetoden du foretrekker for cloning
gb.transportPreference = Foretrukket transport
gb.transportPreferenceDescription = Sett transportmetoden du foretrekker for cloning
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = Norsk

@@ -20,3 +20,3 @@ gb.repository = Repozytorium

gb.ticketOpenDate = Data otwarcia
gb.ticketState = Status
gb.ticketStatus = Status
gb.ticketComments = Komentarze

@@ -87,3 +87,3 @@ gb.view = Widok

gb.viewRestricted = Uwierzytelniony podgl\u0105d, klonowanie i zapis
gb.useTicketsDescription = Rozproszone zg\u0142oszenia Ticgit
gb.useTicketsDescription = Rozproszone zg\u0142oszenia Ticgit
gb.useDocsDescription = Parsuj znaczniki Markdown w repozytorium

@@ -113,3 +113,3 @@ gb.showRemoteBranchesDescription = Poka\u017C zdalne ga\u0142\u0119zie

gb.tokens = Tokeny federacji
gb.tokenAllDescription = Wszystkie repozytoria, u\u017Cytkownicy i ustawienia
gb.tokenAllDescription = Wszystkie repozytoria, u\u017Cytkownicy i ustawienia
gb.tokenUnrDescription = Wszystkie repozytoria i u\u017Cytkownicy

@@ -175,3 +175,2 @@ gb.tokenJurDescription = Wszystkie repozytoria

gb.since = Od
gb.status = Status
gb.bootDate = Data uruchomienia

@@ -368,3 +367,3 @@ gb.servletContainer = Kontener serwlet\u00F3w

gb.busyCollectingGarbage = Przepraszamy, Gitblit jest w trakcie od\u015Bmiecania zasob\u00F3w w {0}
gb.gcPeriod = okres GC
gb.gcPeriod = okres GC
gb.gcPeriodDescription = okres pomi\u0119dzy kolejnymi od\u015Bmieceniami

@@ -469,3 +468,3 @@ gb.gcThreshold = pr\u00F3g GC

gb.at = w
gb.of = z
gb.of = z
gb.in = w

@@ -512,1 +511,4 @@ gb.moreChanges = wszystkie zmiany...

gb.anonymousUser= anonimowy
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = polszczyzna

@@ -1,5 +0,5 @@

gb.repository = reposit�rio
gb.owner = propriet�rio
gb.description = descri��o
gb.lastChange = �ltima altera��o
gb.repository = reposit\u00f3rio
gb.owner = propriet\u00e1rio
gb.description = descri\u00e7\u00e3o
gb.lastChange = \u00faltima altera\u00e7\u00e3o
gb.refs = refs

@@ -11,13 +11,13 @@ gb.tag = tag

gb.commit = commit
gb.tree = �rvore
gb.tree = \u00e1rvore
gb.parent = parent
gb.url = URL
gb.history = hist�rico
gb.history = hist\u00f3rico
gb.raw = raw
gb.object = object
gb.ticketId = ticket id
gb.ticketAssigned = atribu�do
gb.ticketAssigned = atribu\u00eddo
gb.ticketOpenDate = data da abertura
gb.ticketState = estado
gb.ticketComments = coment�rios
gb.ticketStatus = estado
gb.ticketComments = coment\u00e1rios
gb.view = visualizar

@@ -35,9 +35,9 @@ gb.local = local

gb.ticket = ticket
gb.newRepository = novo reposit�rio
gb.newUser = novo usu�rio
gb.newRepository = novo reposit\u00f3rio
gb.newUser = novo usu\u00e1rio
gb.commitdiff = commitdiff
gb.tickets = tickets
gb.pageFirst = primeira
gb.pagePrevious anterior
gb.pageNext = pr�xima
gb.pagePrevious = anterior
gb.pageNext = pr\u00f3xima
gb.head = HEAD

@@ -50,6 +50,6 @@ gb.blame = blame

gb.tagger = tagger
gb.moreHistory = mais hist�rico...
gb.moreHistory = mais hist\u00f3rico...
gb.difftocurrent = diff para a atual
gb.search = pesquisar
gb.searchForAuthor = Procurar por commits cujo autor �
gb.searchForAuthor = Procurar por commits cujo autor \u00e9
gb.searchForCommitter = Procurar por commits commitados por

@@ -60,6 +60,6 @@ gb.addition = adicionados

gb.rename = renomear
gb.metrics = m�tricas
gb.stats = estat�sticas
gb.metrics = m\u00e9tricas
gb.stats = estat\u00edsticas
gb.markdown = markdown
gb.changedFiles = arquivos alterados
gb.changedFiles = arquivos alterados
gb.filesAdded = {0} arquivos adicionados

@@ -76,21 +76,21 @@ gb.filesModified = {0} arquivos modificados

gb.docs = docs
gb.accessRestriction = restri��o de acesso
gb.accessRestriction = restri\u00e7\u00e3o de acesso
gb.name = nome
gb.enableTickets = ativar tickets
gb.enableDocs = ativar documenta��o
gb.enableDocs = ativar documenta\u00e7\u00e3o
gb.save = salvar
gb.showRemoteBranches = mostrar branches remotos
gb.editUsers = editar usu�rios
gb.editUsers = editar usu\u00e1rios
gb.confirmPassword = confirmar password
gb.restrictedRepositories = reposit�rios restritos
gb.restrictedRepositories = reposit\u00f3rios restritos
gb.canAdmin = pode administrar
gb.notRestricted = visualiza��o an�nima, clone, & push
gb.pushRestricted = push aut�nticado
gb.cloneRestricted = clone & push aut�nticados
gb.viewRestricted = view, clone, & push aut�nticados
gb.useTicketsDescription = somente leitura, issues do Ticgit distribu�dos
gb.useDocsDescription = enumerar documenta��o Markdown no reposit�rio
gb.notRestricted = visualiza\u00e7\u00e3o an\u00f4nima, clone, & push
gb.pushRestricted = push aut\u00eanticado
gb.cloneRestricted = clone & push aut\u00eanticados
gb.viewRestricted = view, clone, & push aut\u00eanticados
gb.useTicketsDescription = somente leitura, issues do Ticgit distribu\u00eddos
gb.useDocsDescription = enumerar documenta\u00e7\u00e3o Markdown no reposit\u00f3rio
gb.showRemoteBranchesDescription = mostrar branches remotos
gb.canAdminDescription = pode administrar o server Gitblit
gb.permittedUsers = usu�rios autorizados
gb.permittedUsers = usu\u00e1rios autorizados
gb.isFrozen = congelar

@@ -100,7 +100,7 @@ gb.isFrozenDescription = proibir fazer push

gb.showReadme = mostrar readme
gb.showReadmeDescription = mostrar um arquivo \"leia-me\" na p�gina de apresenta��o do projeto
gb.nameDescription = utilizer a '/' para agrupar reposit�rios. e.g. libraries/mycoollib.git
gb.ownerDescription = o propriet�rio pode editar configura��es do reposit�rio
gb.showReadmeDescription = mostrar um arquivo \"leia-me\" na p\u00e1gina de apresenta\u00e7\u00e3o do projeto
gb.nameDescription = utilizer a '/' para agrupar reposit\u00f3rios. e.g. libraries/mycoollib.git
gb.ownerDescription = o propriet\u00e1rio pode editar configura\u00e7\u00f5es do reposit\u00f3rio
gb.blob = blob
gb.commitActivityTrend = tend�ncia dos commits
gb.commitActivityTrend = tend\u00eancia dos commits
gb.commitActivityDOW = commits por dia da semana

@@ -111,28 +111,28 @@ gb.commitActivityAuthors = principais committers

gb.changePassword = alterar password
gb.isFederated = est� federado
gb.federateThis = federar este reposit�rio
gb.isFederated = est\u00e1 federado
gb.federateThis = federar este reposit\u00f3rio
gb.federateOrigin = federar o origin
gb.excludeFromFederation = excluir da federa��o
gb.excludeFromFederationDescription = bloquear inst�ncias federadas do GitBlit de fazer pull desta conta
gb.tokens = tokens de federa��o
gb.tokenAllDescription = todos reposit�rios, usu�rios & configura��es
gb.tokenUnrDescription = todos reposit�rios & usu�rios
gb.tokenJurDescription = todos reposit�rios
gb.federatedRepositoryDefinitions = defini��es de reposit�rio
gb.federatedUserDefinitions = defini��es de usu�rios
gb.federatedSettingDefinitions = defini��es de configura��es
gb.proposals = propostas de federa��es
gb.excludeFromFederation = excluir da federa\u00e7\u00e3o
gb.excludeFromFederationDescription = bloquear inst\u00e2ncias federadas do GitBlit de fazer pull desta conta
gb.tokens = tokens de federa\u00e7\u00e3o
gb.tokenAllDescription = todos reposit\u00f3rios, usu\u00e1rios & configura\u00e7\u00f5es
gb.tokenUnrDescription = todos reposit\u00f3rios & usu\u00e1rios
gb.tokenJurDescription = todos reposit\u00f3rios
gb.federatedRepositoryDefinitions = defini\u00e7\u00f5es de reposit\u00f3rio
gb.federatedUserDefinitions = defini\u00e7\u00f5es de usu\u00e1rios
gb.federatedSettingDefinitions = defini\u00e7\u00f5es de configura\u00e7\u00f5es
gb.proposals = propostas de federa\u00e7\u00f5es
gb.received = recebidos
gb.type = tipo
gb.token = token
gb.repositories = reposit�rios
gb.repositories = reposit\u00f3rios
gb.proposal = propostas
gb.frequency = frequ�ncia
gb.frequency = frequ\u00eancia
gb.folder = pasta
gb.lastPull = �ltimo pull
gb.nextPull = pr�ximo pull
gb.inclusions = inclus�es
gb.exclusions = exclu�es
gb.lastPull = \u00faltimo pull
gb.nextPull = pr\u00f3ximo pull
gb.inclusions = inclus\u00f5es
gb.exclusions = exclu\u00f5es
gb.registration = cadastro
gb.registrations = cadastro de federa��es
gb.registrations = cadastro de federa\u00e7\u00f5es
gb.sendProposal = enviar proposta

@@ -143,12 +143,12 @@ gb.status = status

gb.headRefDescription = alterar a ref a qual a HEAD aponta. e.g. refs/heads/master
gb.federationStrategy = estrat�gia de federa��o
gb.federationRegistration = cadastro de federa��es
gb.federationResults = resultados dos pulls de federa��es
gb.federationSets = ajustes de federa��es
gb.federationStrategy = estrat\u00e9gia de federa\u00e7\u00e3o
gb.federationRegistration = cadastro de federa\u00e7\u00f5es
gb.federationResults = resultados dos pulls de federa\u00e7\u00f5es
gb.federationSets = ajustes de federa\u00e7\u00f5es
gb.message = mensagem
gb.myUrlDescription = a url de acesso p�blico para a inst�ncia Gitblit
gb.myUrlDescription = a url de acesso p\u00fablico para a inst\u00e2ncia Gitblit
gb.destinationUrl = enviar para
gb.destinationUrlDescription = a url da int�ncia do Gitblit para enviar sua proposta
gb.users = usu�rios
gb.federation = federa��o
gb.destinationUrlDescription = a url da int\u00e2ncia do Gitblit para enviar sua proposta
gb.users = usu\u00e1rios
gb.federation = federa\u00e7\u00e3o
gb.error = erro

@@ -162,3 +162,3 @@ gb.refresh = atualizar

gb.recent = recente
gb.available = dispon�vel
gb.available = dispon\u00edvel
gb.selected = selecionado

@@ -170,9 +170,9 @@ gb.size = tamanho

gb.general = geral
gb.settings = configura��es
gb.settings = configura\u00e7\u00f5es
gb.manage = administrar
gb.lastLogin = �ltimo login
gb.skipSizeCalculation = ignorar c�lculo do tamanho
gb.skipSizeCalculationDescription = n�o calcular o tamanho do reposit�rio (reduz o tempo de load da p�gina)
gb.skipSummaryMetrics = ignorar resumo das m�tricas
gb.skipSummaryMetricsDescription = n�o calcular m�tricas na p�gina de resumo
gb.lastLogin = \u00faltimo login
gb.skipSizeCalculation = ignorar c\u00e1lculo do tamanho
gb.skipSizeCalculationDescription = n\u00e3o calcular o tamanho do reposit\u00f3rio (reduz o tempo de load da p\u00e1gina)
gb.skipSummaryMetrics = ignorar resumo das m\u00e9tricas
gb.skipSummaryMetricsDescription = n\u00e3o calcular m\u00e9tricas na p\u00e1gina de resumo
gb.accessLevel = acesso

@@ -182,10 +182,9 @@ gb.default = default

gb.since = desde
gb.status = status
gb.bootDate = data do boot
gb.servletContainer = servlet container
gb.heapMaximum = heap m�ximo
gb.heapMaximum = heap m\u00e1ximo
gb.heapAllocated = alocar heap
gb.heapUsed = usar heap
gb.free = free
gb.version = vers�o
gb.version = vers\u00e3o
gb.releaseDate = data de release

@@ -196,8 +195,8 @@ gb.date = data

gb.branch = branch
gb.maxHits = hits m�ximos
gb.maxHits = hits m\u00e1ximos
gb.recentActivity = atividade recente
gb.recentActivityStats = �ltimos {0} dias / {1} commits por {2} autores
gb.recentActivityNone = �ltimos {0} dias / nenhum
gb.dailyActivity = atividade di�ria
gb.activeRepositories = reposit�rios ativos
gb.recentActivityStats = \u00faltimos {0} dias / {1} commits por {2} autores
gb.recentActivityNone = \u00faltimos {0} dias / nenhum
gb.dailyActivity = atividade di\u00e1ria
gb.activeRepositories = reposit\u00f3rios ativos
gb.activeAuthors = autores ativos

@@ -208,7 +207,7 @@ gb.commits = commits

gb.teamMembers = membros
gb.teamMemberships = filia��es em equipes
gb.teamMemberships = filia\u00e7\u00f5es em equipes
gb.newTeam = nova equipe
gb.permittedTeams = equipes permitidas
gb.emptyRepository = reposit�rio vazio
gb.repositoryUrl = url do reposit�rio
gb.emptyRepository = reposit\u00f3rio vazio
gb.repositoryUrl = url do reposit\u00f3rio
gb.mailingLists = listas de e-mails

@@ -219,17 +218,17 @@ gb.preReceiveScripts = pre-receive scripts

gb.customFields = campos customizados
gb.customFieldsDescription = campos customizados dispon�veis para Groovy hooks
gb.accessPermissions = permiss�es de acesso
gb.customFieldsDescription = campos customizados dispon\u00edveis para Groovy hooks
gb.accessPermissions = permiss\u00f5es de acesso
gb.filters = filtros
gb.generalDescription = configura��es comuns
gb.accessPermissionsDescription = restringir acesso por usu�rios e equipes
gb.accessPermissionsForUserDescription = ajustar filia��es em equipes ou garantir acesso a reposit�rios espec�ficos
gb.accessPermissionsForTeamDescription = ajustar membros da equipe e garantir acesso a reposit�rios espec�ficos
gb.federationRepositoryDescription = compartilhar este reposit�rio com outros servidores Gitblit
gb.generalDescription = configura\u00e7\u00f5es comuns
gb.accessPermissionsDescription = restringir acesso por usu\u00e1rios e equipes
gb.accessPermissionsForUserDescription = ajustar filia\u00e7\u00f5es em equipes ou garantir acesso a reposit\u00f3rios espec\u00edficos
gb.accessPermissionsForTeamDescription = ajustar membros da equipe e garantir acesso a reposit\u00f3rios espec\u00edficos
gb.federationRepositoryDescription = compartilhar este reposit\u00f3rio com outros servidores Gitblit
gb.hookScriptsDescription = rodar scripts Groovy nos pushes para este servidor Gitblit
gb.reset = reset
gb.pages = p�ginas
gb.pages = p\u00e1ginas
gb.workingCopy = working copy
gb.workingCopyWarning = este reposit�rio tem uma working copy e n�o pode receber pushes
gb.workingCopyWarning = este reposit\u00f3rio tem uma working copy e n\u00e3o pode receber pushes
gb.query = query
gb.queryHelp = Standard query syntax � suportada.<p/><p/>Por favor veja ${querySyntax} para mais detalhes.
gb.queryHelp = Standard query syntax \u00e9 suportada.<p/><p/>Por favor veja ${querySyntax} para mais detalhes.
gb.querySyntax = Lucene Query Parser Syntax

@@ -241,93 +240,93 @@ gb.queryResults = resultados {0} - {1} ({2} hits)

gb.indexedBranches = branches indexados
gb.indexedBranchesDescription = selecione os branches para incluir nos seus �ndices Lucene
gb.noIndexedRepositoriesWarning = nenhum dos seus reposit�rios foram configurados para indexa��o do Lucene
gb.undefinedQueryWarning = a query n�o foi definida!
gb.noSelectedRepositoriesWarning = por favor selecione um ou mais reposit�rios!
gb.luceneDisabled = indexa��o do Lucene est� desabilitada
gb.indexedBranchesDescription = selecione os branches para incluir nos seus \u00edndices Lucene
gb.noIndexedRepositoriesWarning = nenhum dos seus reposit\u00f3rios foram configurados para indexa\u00e7\u00e3o do Lucene
gb.undefinedQueryWarning = a query n\u00e3o foi definida!
gb.noSelectedRepositoriesWarning = por favor selecione um ou mais reposit\u00f3rios!
gb.luceneDisabled = indexa\u00e7\u00e3o do Lucene est\u00e1 desabilitada
gb.failedtoRead = leitura falhou
gb.isNotValidFile = n�o � um arquivo v�lido
gb.isNotValidFile = n\u00e3o \u00e9 um arquivo v\u00e1lido
gb.failedToReadMessage = falha ao ler mensagens default de {0}!
gb.passwordsDoNotMatch = Passwords n�o conferem!
gb.passwordTooShort = Password � muito curto. Tamanho m�nimo s�o {0} caracteres.
gb.passwordsDoNotMatch = Passwords n\u00e3o conferem!
gb.passwordTooShort = Password \u00e9 muito curto. Tamanho m\u00ednimo s\u00e3o {0} caracteres.
gb.passwordChanged = Password alterado com sucesso.
gb.passwordChangeAborted = altera��o do password foi abortada.
gb.pleaseSetRepositoryName = Por favor ajuste o nome do reposit�rio!
gb.illegalLeadingSlash = Refer�ncias a diret�rios raiz come�ando com (/) s�o proibidas.
gb.illegalRelativeSlash = Refer�ncias a diret�rios relativos (../) s�o proibidas.
gb.illegalCharacterRepositoryName = Caractere ilegal ''{0}'' no nome do reposit�rio!
gb.selectAccessRestriction = Por favor selecione a restri��o de acesso!
gb.selectFederationStrategy = Por favor selecione a estrat�gia de federa��o!
gb.passwordChangeAborted = altera\u00e7\u00e3o do password foi abortada.
gb.pleaseSetRepositoryName = Por favor ajuste o nome do reposit\u00f3rio!
gb.illegalLeadingSlash = Refer\u00eancias a diret\u00f3rios raiz come\u00e7ando com (/) s\u00e3o proibidas.
gb.illegalRelativeSlash = Refer\u00eancias a diret\u00f3rios relativos (../) s\u00e3o proibidas.
gb.illegalCharacterRepositoryName = Caractere ilegal ''{0}'' no nome do reposit\u00f3rio!
gb.selectAccessRestriction = Por favor selecione a restri\u00e7\u00e3o de acesso!
gb.selectFederationStrategy = Por favor selecione a estrat\u00e9gia de federa\u00e7\u00e3o!
gb.pleaseSetTeamName = Por favor insira um nome de equipe!
gb.teamNameUnavailable = O nome de equipe ''{0}'' est� indispon�vel.
gb.teamMustSpecifyRepository = Uma equipe deve especificar pelo menos um reposit�rio.
gb.teamNameUnavailable = O nome de equipe ''{0}'' est\u00e1 indispon\u00edvel.
gb.teamMustSpecifyRepository = Uma equipe deve especificar pelo menos um reposit\u00f3rio.
gb.teamCreated = Nova equipe ''{0}'' criada com sucesso.
gb.pleaseSetUsername = Por favor entre com um username!
gb.usernameUnavailable = Username ''{0}'' est� indispon�vel.
gb.combinedMd5Rename = Gitblit est� configurado para usar um hash combinado-md5. Voc� deve inserir um novo password ao renamear a conta.
gb.userCreated = Novo usu�rio ''{0}'' criado com sucesso.
gb.couldNotFindFederationRegistration = N�o foi poss�vel localizar o registro da federa��o!
gb.usernameUnavailable = Username ''{0}'' est\u00e1 indispon\u00edvel.
gb.combinedMd5Rename = Gitblit est\u00e1 configurado para usar um hash combinado-md5. Voc\u00ea deve inserir um novo password ao renamear a conta.
gb.userCreated = Novo usu\u00e1rio ''{0}'' criado com sucesso.
gb.couldNotFindFederationRegistration = N\u00e3o foi poss\u00edvel localizar o registro da federa\u00e7\u00e3o!
gb.failedToFindGravatarProfile = Falha ao localizar um perfil Gravatar para {0}
gb.branchStats = {0} commits e {1} tags em {2}
gb.repositoryNotSpecified = Reposit�rio n�o espec�ficado!
gb.repositoryNotSpecifiedFor = Reposit�rio n�o espec�ficado para {0}!
gb.canNotLoadRepository = N�o foi poss�vel carregar o reposit�rio
gb.commitIsNull = Commit est� nulo
gb.unauthorizedAccessForRepository = Acesso n�o autorizado para o reposit�rio
gb.failedToFindCommit = N�o foi poss�vel achar o commit \"{0}\" em {1} para {2} p�gina!
gb.couldNotFindFederationProposal = N�o foi poss�vel localizar propostas de federa��o!
gb.invalidUsernameOrPassword = username ou password inv�lido!
gb.OneProposalToReview = Existe uma proposta de federa��o aguardando revis�o.
gb.nFederationProposalsToReview = Existem {0} propostas de federa��o aguardando revis�o.
gb.couldNotFindTag = N�o foi poss�vel localizar a tag {0}
gb.couldNotCreateFederationProposal = N�o foi poss�vel criar uma proposta de federation!
gb.repositoryNotSpecified = Reposit\u00f3rio n\u00e3o espec\u00edficado!
gb.repositoryNotSpecifiedFor = Reposit\u00f3rio n\u00e3o espec\u00edficado para {0}!
gb.canNotLoadRepository = N\u00e3o foi poss\u00edvel carregar o reposit\u00f3rio
gb.commitIsNull = Commit est\u00e1 nulo
gb.unauthorizedAccessForRepository = Acesso n\u00e3o autorizado para o reposit\u00f3rio
gb.failedToFindCommit = N\u00e3o foi poss\u00edvel achar o commit \"{0}\" em {1} para {2} p\u00e1gina!
gb.couldNotFindFederationProposal = N\u00e3o foi poss\u00edvel localizar propostas de federa\u00e7\u00e3o!
gb.invalidUsernameOrPassword = username ou password inv\u00e1lido!
gb.OneProposalToReview = Existe uma proposta de federa\u00e7\u00e3o aguardando revis\u00e3o.
gb.nFederationProposalsToReview = Existem {0} propostas de federa\u00e7\u00e3o aguardando revis\u00e3o.
gb.couldNotFindTag = N\u00e3o foi poss\u00edvel localizar a tag {0}
gb.couldNotCreateFederationProposal = N\u00e3o foi poss\u00edvel criar uma proposta de federation!
gb.pleaseSetGitblitUrl = Por favor insira sua url do Gitblit!
gb.pleaseSetDestinationUrl = Por favor insira a url de destino para sua proposta!
gb.proposalReceived = Proposta recebida com sucesso por {0}.
gb.noGitblitFound = Desculpe, {0} n�o localizou uma inst�ncia do Gitblit em {1}.
gb.noProposals = Desculpe, {0} n�o est� aceitando propostas agora.
gb.noFederation = Desculpe, {0} n�o est� configurado com nenhuma int�ncia do Gitblit.
gb.proposalFailed = Desculpe, {0} n�o recebeu nenhum dado de proposta!
gb.noGitblitFound = Desculpe, {0} n\u00e3o localizou uma inst\u00e2ncia do Gitblit em {1}.
gb.noProposals = Desculpe, {0} n\u00e3o est\u00e1 aceitando propostas agora.
gb.noFederation = Desculpe, {0} n\u00e3o est\u00e1 configurado com nenhuma int\u00e2ncia do Gitblit.
gb.proposalFailed = Desculpe, {0} n\u00e3o recebeu nenhum dado de proposta!
gb.proposalError = Desculpe, {0} reportou que um erro inesperado ocorreu!
gb.failedToSendProposal = N�o foi poss�vel enviar a proposta!
gb.userServiceDoesNotPermitAddUser = {0} n�o permite adicionar uma conta de usu�rio!
gb.userServiceDoesNotPermitPasswordChanges = {0} n�o permite altera��es no password!
gb.failedToSendProposal = N\u00e3o foi poss\u00edvel enviar a proposta!
gb.userServiceDoesNotPermitAddUser = {0} n\u00e3o permite adicionar uma conta de usu\u00e1rio!
gb.userServiceDoesNotPermitPasswordChanges = {0} n\u00e3o permite altera\u00e7\u00f5es no password!
gb.displayName = nome
gb.emailAddress = e-mail
gb.errorAdminLoginRequired = Administra��o requer um login
gb.errorOnlyAdminMayCreateRepository = Somente umadministrador pode criar um reposit�rio
gb.errorOnlyAdminOrOwnerMayEditRepository = Somente umadministrador pode editar um reposit�rio
gb.errorAdministrationDisabled = Administra��o est� desabilitada
gb.lastNDays = �ltimos {0} dias
gb.errorAdminLoginRequired = Administra\u00e7\u00e3o requer um login
gb.errorOnlyAdminMayCreateRepository = Somente umadministrador pode criar um reposit\u00f3rio
gb.errorOnlyAdminOrOwnerMayEditRepository = Somente umadministrador pode editar um reposit\u00f3rio
gb.errorAdministrationDisabled = Administra\u00e7\u00e3o est\u00e1 desabilitada
gb.lastNDays = \u00faltimos {0} dias
gb.completeGravatarProfile = Profile completo em Gravatar.com
gb.none = nenhum
gb.line = linha
gb.content = conte�do
gb.content = conte\u00fado
gb.empty = vazio
gb.inherited = herdado
gb.deleteRepository = Deletar reposit�rio \"{0}\"?
gb.repositoryDeleted = Reposit�rio ''{0}'' deletado.
gb.repositoryDeleteFailed = N�o foi poss�vel apagar o reposit�rio ''{0}''!
gb.deleteUser = Deletar usu�rio \"{0}\"?
gb.userDeleted = Usu�rio ''{0}'' deletado.
gb.userDeleteFailed = N�o foi poss�vel apagar o usu�rio ''{0}''!
gb.deleteRepository = Deletar reposit\u00f3rio \"{0}\"?
gb.repositoryDeleted = Reposit\u00f3rio ''{0}'' deletado.
gb.repositoryDeleteFailed = N\u00e3o foi poss\u00edvel apagar o reposit\u00f3rio ''{0}''!
gb.deleteUser = Deletar usu\u00e1rio \"{0}\"?
gb.userDeleted = Usu\u00e1rio ''{0}'' deletado.
gb.userDeleteFailed = N\u00e3o foi poss\u00edvel apagar o usu\u00e1rio ''{0}''!
gb.time.justNow = agora mesmo
gb.time.today = hoje
gb.time.yesterday = ontem
gb.time.minsAgo = h� {0} minutos
gb.time.hoursAgo = h� {0} horas
gb.time.daysAgo = h� {0} dias
gb.time.weeksAgo = h� {0} semanas
gb.time.monthsAgo = h� {0} meses
gb.time.oneYearAgo = h� 1 ano
gb.time.yearsAgo = h� {0} anos
gb.time.minsAgo = h\u00e1 {0} minutos
gb.time.hoursAgo = h\u00e1 {0} horas
gb.time.daysAgo = h\u00e1 {0} dias
gb.time.weeksAgo = h\u00e1 {0} semanas
gb.time.monthsAgo = h\u00e1 {0} meses
gb.time.oneYearAgo = h\u00e1 1 ano
gb.time.yearsAgo = h\u00e1 {0} anos
gb.duration.oneDay = 1 dia
gb.duration.days = {0} dias
gb.duration.oneMonth = 1 m�s
gb.duration.oneMonth = 1 m\u00eas
gb.duration.months = {0} meses
gb.duration.oneYear = 1 ano
gb.duration.years = {0} anos
gb.authorizationControl = controle de autoriza��o
gb.allowAuthenticatedDescription = conceder permiss�o RW+ para todos os usu�rios aut�nticados
gb.allowNamedDescription = conceder permiss�es refinadas para usu�rios escolhidos ou equipes
gb.markdownFailure = N�o foi poss�vel converter conte�do Markdown!
gb.authorizationControl = controle de autoriza\u00e7\u00e3o
gb.allowAuthenticatedDescription = conceder permiss\u00e3o RW+ para todos os usu\u00e1rios aut\u00eanticados
gb.allowNamedDescription = conceder permiss\u00f5es refinadas para usu\u00e1rios escolhidos ou equipes
gb.markdownFailure = N\u00e3o foi poss\u00edvel converter conte\u00fado Markdown!
gb.clearCache = limpar o cache

@@ -342,28 +341,28 @@ gb.projects = projetos

gb.repositoryForked = fork feito em {0}
gb.repositoryForkFailed= n�o foi poss�vel fazer fork
gb.personalRepositories = reposit�rios pessoais
gb.repositoryForkFailed= n\u00e3o foi poss\u00edvel fazer fork
gb.personalRepositories = reposit\u00f3rios pessoais
gb.allowForks = permitir forks
gb.allowForksDescription = permitir usu�rios autorizados a fazer fork deste reposit�rio
gb.allowForksDescription = permitir usu\u00e1rios autorizados a fazer fork deste reposit\u00f3rio
gb.forkedFrom = forked de
gb.canFork = pode fazer fork
gb.canForkDescription = pode fazer fork de reposit�rios autorizados para reposit�rios pessoais
gb.canForkDescription = pode fazer fork de reposit\u00f3rios autorizados para reposit\u00f3rios pessoais
gb.myFork = visualizar meu fork
gb.forksProhibited = forks proibidos
gb.forksProhibitedWarning = este reposit�rio pro�be forks
gb.noForks = {0} n�o possui forks
gb.forkNotAuthorized = desculpe, voc� n�o est� autorizado a fazer fork de {0}
gb.forksProhibitedWarning = este reposit\u00f3rio pro\u00edbe forks
gb.noForks = {0} n\u00e3o possui forks
gb.forkNotAuthorized = desculpe, voc\u00ea n\u00e3o est\u00e1 autorizado a fazer fork de {0}
gb.forkInProgress = fork em progresso
gb.preparingFork = preparando seu fork...
gb.isFork = � fork
gb.isFork = \u00e9 fork
gb.canCreate = pode criar
gb.canCreateDescription = pode criar reposit�rios pessoais
gb.illegalPersonalRepositoryLocation = seu reposit�rio pessoal deve estar localizado em \"{0}\"
gb.canCreateDescription = pode criar reposit\u00f3rios pessoais
gb.illegalPersonalRepositoryLocation = seu reposit\u00f3rio pessoal deve estar localizado em \"{0}\"
gb.verifyCommitter = verificar committer
gb.verifyCommitterDescription = requer a identidade do committer para combinar com uma conta do Gitblt
gb.verifyCommitterNote = todos os merges requerem "--no-ff" para impor a identidade do committer
gb.repositoryPermissions = permiss�es de reposit�rio
gb.userPermissions = permiss�es de usu�rio
gb.teamPermissions = permiss�es de equipe
gb.repositoryPermissions = permiss\u00f5es de reposit\u00f3rio
gb.userPermissions = permiss\u00f5es de usu\u00e1rio
gb.teamPermissions = permiss\u00f5es de equipe
gb.add = add
gb.noPermission = APAGAR ESTA PERMISS�O
gb.noPermission = APAGAR ESTA PERMISS\u00c3O
gb.excludePermission = {0} (excluir)

@@ -376,25 +375,25 @@ gb.viewPermission = {0} (visualizar)

gb.rewindPermission = {0} (push, ref creation+deletion+rewind)
gb.permission = permiss�o
gb.regexPermission = esta permiss�o foi configurada atrav�s da express�o regular \"{0}\"
gb.permission = permiss\u00e3o
gb.regexPermission = esta permiss\u00e3o foi configurada atrav\u00e9s da express\u00e3o regular \"{0}\"
gb.accessDenied = acesso negado
gb.busyCollectingGarbage = desculpe, o Gitblit est� ocupado coletando lixo em {0}
gb.gcPeriod = per�odo do GC
gb.gcPeriodDescription = dura��o entre as coletas de lixo
gb.gcThreshold = limite do GC
gb.gcThresholdDescription = tamanho total m�nimo de objetos \"abandonados\" que ativam a coleta de lixo
gb.ownerPermission = propriet�rio do reposit�rio
gb.busyCollectingGarbage = desculpe, o Gitblit est\u00e1 ocupado coletando lixo em {0}
gb.gcPeriod = per\u00edodo do GC
gb.gcPeriodDescription = dura\u00e7\u00e3o entre as coletas de lixo
gb.gcThreshold = limite do GC
gb.gcThresholdDescription = tamanho total m\u00ednimo de objetos \"abandonados\" que ativam a coleta de lixo
gb.ownerPermission = propriet\u00e1rio do reposit\u00f3rio
gb.administrator = administrador
gb.administratorPermission = administrador do Gitblit
gb.team = equipe
gb.teamPermission = permiss�o concedida pela filia��o a equipe \"{0}\"
gb.teamPermission = permiss\u00e3o concedida pela filia\u00e7\u00e3o a equipe \"{0}\"
gb.missing = faltando!
gb.missingPermission = o reposit�rio para esta permiss�o est� faltando!
gb.mutable = mut�vel
gb.specified = espec�fico
gb.missingPermission = o reposit\u00f3rio para esta permiss\u00e3o est\u00e1 faltando!
gb.mutable = mut\u00e1vel
gb.specified = espec\u00edfico
gb.effective = efetivo
gb.organizationalUnit = unidade organizacional
gb.organization = organiza��o
gb.organization = organiza\u00e7\u00e3o
gb.locality = localidade
gb.stateProvince = estado ou prov�ncia
gb.countryCode = c�digo do pa�s
gb.stateProvince = estado ou prov\u00edncia
gb.countryCode = c\u00f3digo do pa\u00eds
gb.properties = propriedades

@@ -406,3 +405,3 @@ gb.issued = emitido

gb.revoked = revogado
gb.serialNumber = n�mero serial
gb.serialNumber = n\u00famero serial
gb.certificates = certificados

@@ -414,3 +413,3 @@ gb.newCertificate = novo certificado

gb.ok = ok
gb.invalidExpirationDate = data de expira��o inv�lida!
gb.invalidExpirationDate = data de expira\u00e7\u00e3o inv\u00e1lida!
gb.passwordHintRequired = dica de password requerida!

@@ -420,17 +419,17 @@ gb.viewCertificate = visualizar certificado

gb.issuer = emissor
gb.validFrom = v�lido a partir de
gb.validUntil = v�lido at�
gb.publicKey = chave p�blica
gb.validFrom = v\u00e1lido a partir de
gb.validUntil = v\u00e1lido at\u00e9
gb.publicKey = chave p\u00fablica
gb.signatureAlgorithm = algoritmo de assinatura
gb.sha1FingerPrint = digital SHA-1
gb.sha1FingerPrint = digital SHA-1
gb.md5FingerPrint = digital MD5
gb.reason = raz�o
gb.revokeCertificateReason = Por selecione a raz�o da revoga��o do certificado
gb.unspecified = n�o espec�fico
gb.reason = raz\u00e3o
gb.revokeCertificateReason = Por selecione a raz\u00e3o da revoga\u00e7\u00e3o do certificado
gb.unspecified = n\u00e3o espec\u00edfico
gb.keyCompromise = comprometimento de chave
gb.caCompromise = compromisso CA
gb.affiliationChanged = afilia��o foi alterada
gb.superseded = substitu�das
gb.cessationOfOperation = cessa��o de funcionamento
gb.privilegeWithdrawn = privil�gio retirado
gb.affiliationChanged = afilia\u00e7\u00e3o foi alterada
gb.superseded = substitu\u00eddas
gb.cessationOfOperation = cessa\u00e7\u00e3o de funcionamento
gb.privilegeWithdrawn = privil\u00e9gio retirado
gb.time.inMinutes = em {0} minutos

@@ -442,8 +441,8 @@ gb.time.inHours = em {0} horas

gb.newSSLCertificate = novo servidor de certificado SSL
gb.newCertificateDefaults = novos padr�es de certifica��o
gb.duration = dura��o
gb.certificateRevoked = Certificado {0, n�mero, 0} foi revogado
gb.newCertificateDefaults = novos padr\u00f5es de certifica\u00e7\u00e3o
gb.duration = dura\u00e7\u00e3o
gb.certificateRevoked = Certificado {0, n\u00famero, 0} foi revogado
gb.clientCertificateGenerated = Novo certificado cliente para {0} foi gerado com sucesso
gb.sslCertificateGenerated = Novo servidor de certificado SSL gerado com sucesso para {0}
gb.newClientCertificateMessage = OBSERVA��O:\nO 'password' n�o � o password do usu�rio mas sim o password usado para proteger a keystore. Este password n�o ser� salvo ent�o voc� tamb�m inserir uma dica que ser� inclu�da nas instru��es de LEIA-ME do usu�rio.
gb.newClientCertificateMessage = OBSERVA\u00c7\u00c3O:\nO 'password' n\u00e3o \u00e9 o password do usu\u00e1rio mas sim o password usado para proteger a keystore. Este password n\u00e3o ser\u00e1 salvo ent\u00e3o voc\u00ea tamb\u00e9m inserir uma dica que ser\u00e1 inclu\u00edda nas instru\u00e7\u00f5es de LEIA-ME do usu\u00e1rio.
gb.certificate = certificado

@@ -455,24 +454,24 @@ gb.emailCertificateBundle = pacote certificado de cliente de email

gb.warning = warning
gb.jceWarning = Seu Java Runtime Environment n�o tem os arquivos \"JCE Unlimited Strength Jurisdiction Policy\".\nIsto ir� limitar o tamanho dos passwords que voc� usar� para encriptar suas keystores para 7 caracteres.\nEstes arquivos de pol�ticas s�o um download opcional da Oracle.\n\nVoc� gostaria de continuar e gerar os certificados de infraestrutura de qualquer forma?\n\nRespondendo "N�o" ir� redirecionar o seu browser para a p�gina de downloads da Oracle, de onde voc� poder� fazer download desses arquivos.
gb.maxActivityCommits = limitar exibi��o de commits
gb.maxActivityCommitsDescription = quantidade m�xima de commits para contribuir para a p�gina de atividade
gb.jceWarning = Seu Java Runtime Environment n\u00e3o tem os arquivos \"JCE Unlimited Strength Jurisdiction Policy\".\nIsto ir\u00e1 limitar o tamanho dos passwords que voc\u00ea usar\u00e1 para encriptar suas keystores para 7 caracteres.\nEstes arquivos de pol\u00edticas s\u00e3o um download opcional da Oracle.\n\nVoc\u00ea gostaria de continuar e gerar os certificados de infraestrutura de qualquer forma?\n\nRespondendo "N\u00e3o" ir\u00e1 redirecionar o seu browser para a p\u00e1gina de downloads da Oracle, de onde voc\u00ea poder\u00e1 fazer download desses arquivos.
gb.maxActivityCommits = limitar exibi\u00e7\u00e3o de commits
gb.maxActivityCommitsDescription = quantidade m\u00e1xima de commits para contribuir para a p\u00e1gina de atividade
gb.noMaximum = ilimitado
gb.attributes = atributos
gb.serveCertificate = servir https com este certificado
gb.sslCertificateGeneratedRestart = Novo certificado SSL de servidor gerado com sucesso para {0}.\nVoc� deve reiniciar o Gitblit para usar o novo certificado.\n\nSe voc� estiver executando com o par�metro '--alias', voc� precisar� alter�-lo para ''--alias {0}''.
gb.sslCertificateGeneratedRestart = Novo certificado SSL de servidor gerado com sucesso para {0}.\nVoc\u00ea deve reiniciar o Gitblit para usar o novo certificado.\n\nSe voc\u00ea estiver executando com o par\u00e2metro '--alias', voc\u00ea precisar\u00e1 alter\u00e1-lo para ''--alias {0}''.
gb.validity = validade
gb.siteName = nome do site
gb.siteNameDescription = breve, mas ainda assim um nome descritivo para seu servidor
gb.excludeFromActivity = excluir da p�gina de atividades
gb.isSparkleshared = reposit�rio � Sparkleshared
gb.owners = propriet�rios
gb.sessionEnded = A Sess�o foi encerrada
gb.closeBrowser = Por favor feche a tela do browser para encerrar a sess�o apropriadamente.
gb.doesNotExistInTree = {0} n�o existe na �rvore {1}
gb.excludeFromActivity = excluir da p\u00e1gina de atividades
gb.isSparkleshared = reposit\u00f3rio \u00e9 Sparkleshared
gb.owners = propriet\u00e1rios
gb.sessionEnded = A Sess\u00e3o foi encerrada
gb.closeBrowser = Por favor feche a tela do browser para encerrar a sess\u00e3o apropriadamente.
gb.doesNotExistInTree = {0} n\u00e3o existe na \u00e1rvore {1}
gb.enableIncrementalPushTags = ativar push tags incrementais
gb.useIncrementalPushTagsDescription = quando fizer push, automaticamente taguear cada branch com um n�mero de revis�o incremental
gb.incrementalPushTagMessage = [{0}] branch foi tagueado autom�ticamente depois do push
gb.externalPermissions = {0} permiss�es de acesso s�o externalizadas
gb.viewAccess = Voc� n�o tem permiss�o para ler ou escrever o Gitblit
gb.overview = vis�o geral
gb.useIncrementalPushTagsDescription = quando fizer push, automaticamente taguear cada branch com um n\u00famero de revis\u00e3o incremental
gb.incrementalPushTagMessage = [{0}] branch foi tagueado autom\u00e1ticamente depois do push
gb.externalPermissions = {0} permiss\u00f5es de acesso s\u00e3o externalizadas
gb.viewAccess = Voc\u00ea n\u00e3o tem permiss\u00e3o para ler ou escrever o Gitblit
gb.overview = vis\u00e3o geral
gb.dashboard = dashboard

@@ -488,3 +487,3 @@ gb.monthlyActivity = atividade mensal

gb.in = em
gb.moreChanges = todas mudan�as...
gb.moreChanges = todas mudan\u00e7as...
gb.pushedNCommitsTo = fez push de {0} commits para

@@ -496,3 +495,3 @@ gb.pushedOneCommitTo = fez push de 1 commit para

gb.byOneAuthor = por {0}
gb.viewComparison = veja uma compara��o desses {0} commits \u00bb
gb.viewComparison = veja uma compara\u00e7\u00e3o desses {0} commits \u00bb
gb.nMoreCommits = {0} mais commits \u00bb

@@ -506,3 +505,3 @@ gb.oneMoreCommit = mais 1 commit \u00bb

gb.deletedBranch = branch deletado
gb.createdNewPullRequest = requisi��es de pull foram criadas
gb.createdNewPullRequest = requisi\u00e7\u00f5es de pull foram criadas
gb.mergedPullRequest = pull request mergeado

@@ -513,10 +512,10 @@ gb.rewind = REBOBINAR

gb.stargazers = favoritos
gb.starredRepositories = reposit�ries favoritos
gb.failedToUpdateUser = Falha ao atualizar a conta de usu�rio!
gb.myRepositories = meus reposit�rios
gb.noActivity = n�o houve atividade no �ltimos {0} dias
gb.findSomeRepositories = localizar alguns reposit�rios
gb.metricAuthorExclusions = exclus�es de m�tricas de autor
gb.starredRepositories = reposit\u00f3ries favoritos
gb.failedToUpdateUser = Falha ao atualizar a conta de usu\u00e1rio!
gb.myRepositories = meus reposit\u00f3rios
gb.noActivity = n\u00e3o houve atividade no \u00faltimos {0} dias
gb.findSomeRepositories = localizar alguns reposit\u00f3rios
gb.metricAuthorExclusions = exclus\u00f5es de m\u00e9tricas de autor
gb.myDashboard = meu dashboard
gb.failedToFindAccount = falha ao localizar a conta do usu�rio ''{0}''
gb.failedToFindAccount = falha ao localizar a conta do usu\u00e1rio ''{0}''
gb.reflog = reflog

@@ -530,3 +529,6 @@ gb.active = ativo

gb.todaysActivityNone = hoje / nenhum
gb.noActivityToday = n�o houve atividade hoje
gb.anonymousUser= an�nimo
gb.noActivityToday = n\u00e3o houve atividade hoje
gb.anonymousUser= an\u00f4nimo
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = Portugu\u00eas
gb.repository = \u7248\u672c\u5e93
gb.owner = \u62e5\u6709\u8005
gb.owner = \u6240\u6709\u8005
gb.description = \u63cf\u8ff0
gb.lastChange = \u6700\u540e\u4fee\u6539
gb.refs = refs
gb.refs = \u5206\u652f
gb.tag = \u6807\u7b7e

@@ -11,13 +11,12 @@ gb.tags = \u6807\u7b7e

gb.commit = \u63d0\u4ea4
gb.age = age
gb.age = \u65f6\u95f4
gb.tree = \u76ee\u5f55
gb.parent = parent
gb.parent = \u4e0a\u4e00\u7248\u672c
gb.url = URL
gb.history = \u5386\u53f2
gb.raw = \u539f\u59cb\u6587\u6863
gb.object = object
gb.ticketId = \u5de5\u5355\u7f16\u53f7
gb.object = \u5bf9\u8c61
gb.ticketId = \u95ee\u9898\u7f16\u53f7
gb.ticketAssigned = \u5206\u914d\u60c5\u51b5
gb.ticketOpenDate = \u5f00\u542f\u65e5\u671f
gb.ticketState = \u72b6\u6001
gb.ticketComments = \u8bc4\u8bba

@@ -35,7 +34,7 @@ gb.view = \u67e5\u770b

gb.summary = \u6982\u51b5
gb.ticket = \u5de5\u5355
gb.ticket = \u95ee\u9898
gb.newRepository = \u521b\u5efa\u7248\u672c\u5e93
gb.newUser = \u6dfb\u52a0\u7528\u6237
gb.commitdiff = \u63d0\u4ea4\u5bf9\u6bd4
gb.tickets = \u5de5\u5355
gb.tickets = \u95ee\u9898
gb.pageFirst = \u9996\u9875

@@ -60,11 +59,11 @@ gb.pagePrevious = \u524d\u4e00\u9875

gb.rename = \u91cd\u547d\u540d
gb.metrics = \u7edf\u8ba1\u56fe\u8868
gb.metrics = \u7edf\u8ba1
gb.stats = \u7edf\u8ba1
gb.markdown = markdown
gb.changedFiles = \u5df2\u4fee\u6539\u6587\u4ef6
gb.filesAdded = {0}\u4e2a\u6587\u4ef6\u5df2\u6dfb\u52a0
gb.filesModified = {0}\u4e2a\u6587\u4ef6\u5df2\u4fee\u6539
gb.filesDeleted = {0}\u4e2a\u6587\u4ef6\u5df2\u5220\u9664
gb.filesCopied = {0} \u6587\u4ef6\u5df2\u590d\u5236
gb.filesRenamed = {0} \u6587\u4ef6\u5df2\u91cd\u547d\u540d
gb.markdown = Markdown
gb.changedFiles = \u6587\u4ef6\u5df2\u4fee\u6539
gb.filesAdded = \u5df2\u6dfb\u52a0{0}\u4e2a\u6587\u4ef6
gb.filesModified = \u5df2\u4fee\u6539{0}\u4e2a\u6587\u4ef6
gb.filesDeleted = \u5df2\u5220\u9664{0}\u4e2a\u6587\u4ef6
gb.filesCopied = \u5df2\u590d\u5236{0}\u4e2a\u6587\u4ef6
gb.filesRenamed = \u5df2\u91cd\u547d\u540d{0}\u4e2a\u6587\u4ef6
gb.missingUsername = \u7528\u6237\u540d\u4e0d\u5b58\u5728

@@ -78,4 +77,4 @@ gb.edit = \u7f16\u8f91

gb.name = \u540d\u79f0
gb.enableTickets = \u5141\u8bb8\u4f7f\u7528\u5de5\u5355
gb.enableDocs = \u5141\u8bb8\u4f7f\u7528\u6587\u6863
gb.enableTickets = \u542f\u7528\u95ee\u9898
gb.enableDocs = \u542f\u7528\u6587\u6863
gb.save = \u4fdd\u5b58

@@ -85,33 +84,33 @@ gb.showRemoteBranches = \u663e\u793a\u8fdc\u7a0b\u5206\u652f

gb.confirmPassword = \u786e\u8ba4\u5bc6\u7801
gb.restrictedRepositories = \u53d7\u9650\u7248\u672c\u5e93
gb.restrictedRepositories = \u53d7\u9650\u7684\u7248\u672c\u5e93
gb.canAdmin = \u7ba1\u7406\u6743\u9650
gb.notRestricted = \u533f\u540d\u6d4f\u89c8\uff0c\u514b\u9686\u4e0e\u63a8\u9001
gb.pushRestricted = \u8ba4\u8bc1\u63a8\u9001
gb.cloneRestricted = \u8ba4\u8bc1\u514b\u9686\u4e0e\u63a8\u9001
gb.viewRestricted = \u8ba4\u8bc1\u6d4f\u89c8\uff0c\u514b\u9686\u4e0e\u63a8\u9001
gb.useTicketsDescription = \u53ea\u8bfb\u5206\u5e03\u5f0f Ticgit \u4e8b\u52a1
gb.pushRestricted = \u63a8\u9001\uff08\u9700\u8981\u8ba4\u8bc1\uff09
gb.cloneRestricted = \u514b\u9686\u4e0e\u63a8\u9001\uff08\u9700\u8981\u8ba4\u8bc1\uff09
gb.viewRestricted = \u6d4f\u89c8\uff0c\u514b\u9686\u4e0e\u63a8\u9001\uff08\u9700\u8981\u8ba4\u8bc1\uff09
gb.useTicketsDescription = readonly, distributed Ticgit issues
gb.useDocsDescription = \u5217\u51fa\u7248\u672c\u5e93\u5185\u6240\u6709 Markdown \u6587\u6863
gb.showRemoteBranchesDescription = \u663e\u793a\u8fdc\u7a0b\u5206\u652f
gb.canAdminDescription = Gitblit \u670d\u52a1\u5668\u7ba1\u7406\u5458
gb.permittedUsers = \u5141\u8bb8\u7528\u6237
gb.permittedUsers = \u6388\u6743\u7684\u7528\u6237
gb.isFrozen = \u88ab\u51bb\u7ed3
gb.isFrozenDescription = \u7981\u6b62\u63a8\u9001\u64cd\u4f5c
gb.zip = zip
gb.showReadme = \u663e\u793areadme
gb.showReadmeDescription = \u5728\u6982\u51b5\u9875\u9762\u663e\u793a \\"readme\\" Markdown \u6587\u4ef6
gb.showReadme = \u663e\u793areadme\u6587\u4ef6
gb.showReadmeDescription = \u5728\u6982\u51b5\u9875\u9762\u663e\u793a \"readme\" Markdown \u6587\u4ef6
gb.nameDescription = \u4f7f\u7528 '/' \u5bf9\u7248\u672c\u5e93\u8fdb\u884c\u5206\u7ec4 \u4f8b\u5982\uff1a libraries/mycoollib.git
gb.ownerDescription = \u521b\u5efa\u8005\u53ef\u4ee5\u7f16\u8f91\u7248\u672c\u5e93\u5c5e\u6027
gb.ownerDescription = \u6240\u6709\u8005\u53ef\u4ee5\u7f16\u8f91\u7248\u672c\u5e93\u5c5e\u6027
gb.blob = blob
gb.commitActivityTrend = \u63d0\u4ea4\u6d3b\u52a8\u8d8b\u52bf
gb.commitActivityDOW = \u6bcf\u5468\u63d0\u4ea4\u6d3b\u52a8
gb.commitActivityAuthors = \u63d0\u4ea4\u6d3b\u52a8\u4e3b\u8981\u7528\u6237
gb.feed = feed
gb.commitActivityAuthors = \u4e3b\u8981\u6d3b\u52a8\u7528\u6237
gb.feed = \u8ba2\u9605
gb.cancel = \u53d6\u6d88
gb.changePassword = \u4fee\u6539\u5bc6\u7801
gb.isFederated = is federated
gb.federateThis = federate this repository
gb.federateOrigin = federate the origin
gb.excludeFromFederation = exclude from federation
gb.isFederated = \u5df2\u7ecf federated
gb.federateThis = \u4e0e\u6b64\u7248\u672c\u5e93 federate
gb.federateOrigin = \u4e0e\u8fdc\u7a0b\u7248\u672c\u5e93 federate
gb.excludeFromFederation = \u4ece federation \u4e2d\u6392\u9664
gb.excludeFromFederationDescription = \u7981\u6b62\u5df2 federated \u7684 Gitblit \u5b9e\u4f8b\u4ece\u672c\u8d26\u6237\u62c9\u53d6
gb.tokens = federation tokens
gb.tokens = federation token
gb.tokenAllDescription = \u6240\u6709\u7248\u672c\u5e93\uff0c\u7528\u6237\u548c\u8bbe\u7f6e

@@ -124,3 +123,3 @@ gb.tokenUnrDescription = \u6240\u6709\u7248\u672c\u5e93\u548c\u7528\u6237

gb.proposals = federation proposals
gb.received = \u5df2\u63a5\u53d7
gb.received = \u5df2\u63a5\u6536
gb.type = \u7c7b\u522b

@@ -137,16 +136,16 @@ gb.token = token

gb.registration = \u6ce8\u518c
gb.registrations = federation \u6ce8\u518c
gb.registrations = federation registrations
gb.sendProposal = \u63d0\u4ea4\u5efa\u8bae
gb.status = \u72b6\u6001
gb.origin = \u8fdc\u7aef
gb.origin = \u8fdc\u7a0b
gb.headRef = \u9ed8\u8ba4\u5206\u652f (HEAD)
gb.headRefDescription = \u4fee\u6539 HEAD \u6240\u6307\u5411\u7684 ref\u3002 \u4f8b\u5982: refs/heads/master
gb.federationStrategy = federation \u7b56\u7565
gb.federationRegistration = federation \u6ce8\u518c
gb.federationResults = federation \u62c9\u53d6\u7ed3\u679c
gb.federationSets = federation \u96c6
gb.federationRegistration = federation registration
gb.federationResults = federation results
gb.federationSets = federation sets
gb.message = \u6d88\u606f
gb.myUrlDescription = \u60a8\u7684 Gitblit \u5b9e\u4f8b\u7684\u516c\u5171\u8bbf\u95ee\u7f51\u5740
gb.destinationUrl = \u53d1\u9001\u81f3
gb.destinationUrlDescription = \u4f60\u6240\u8981\u53d1\u9001\u5efa\u8bae\u7684 Gitblit \u5b9e\u4f8b\u7f51\u5740
gb.destinationUrlDescription = \u4f60\u5e0c\u671b\u53d1\u9001\u7684 Gitblit \u5b9e\u4f8b\u7f51\u5740
gb.users = \u7528\u6237

@@ -158,3 +157,3 @@ gb.federation = federation

gb.clone = \u514b\u9686
gb.filter = \u8fc7\u6ee4
gb.filter = \u7b5b\u9009
gb.create = \u521b\u5efa

@@ -176,10 +175,9 @@ gb.servers = \u670d\u52a1\u5668

gb.skipSummaryMetrics = \u5ffd\u7565\u6982\u51b5\u5904\u7684 metrics
gb.skipSummaryMetricsDescription = \u6982\u51b5\u9875\u9762\u4e0d\u8ba1\u7b97metrics\uff08\u8282\u7701\u9875\u9762\u8f7d\u5165\u65f6\u95f4\uff09
gb.accessLevel = \u8bbf\u95ee\u7ea7\u522b
gb.skipSummaryMetricsDescription = \u6982\u51b5\u9875\u9762\u4e0d\u8ba1\u7b97 metrics\uff08\u8282\u7701\u9875\u9762\u8f7d\u5165\u65f6\u95f4\uff09
gb.accessLevel = \u8bbf\u95ee\u6743\u9650
gb.default = \u9ed8\u8ba4
gb.setDefault = \u9ed8\u8ba4\u8bbe\u7f6e
gb.since = \u81ea\u4ece
gb.status = \u72b6\u6001
gb.bootDate = \u542f\u52a8\u65e5\u671f
gb.servletContainer = servlet container
gb.servletContainer = servlet \u5bb9\u5668
gb.heapMaximum = \u6700\u5927\u5806

@@ -208,3 +206,3 @@ gb.heapAllocated = \u5df2\u5206\u914d\u5806

gb.newTeam = \u6dfb\u52a0\u56e2\u961f
gb.permittedTeams = \u5141\u8bb8\u56e2\u961f
gb.permittedTeams = \u6388\u6743\u7684\u56e2\u961f
gb.emptyRepository = \u7a7a\u7248\u672c\u5e93

@@ -217,11 +215,11 @@ gb.repositoryUrl = \u7248\u672c\u5e93\u5730\u5740

gb.customFields = \u81ea\u5b9a\u4e49\u57df
gb.customFieldsDescription = Groovy\u811a\u672c\u652f\u6301\u7684\u81ea\u5b9a\u4e49\u57df
gb.customFieldsDescription = Groovy \u811a\u672c\u652f\u6301\u7684\u81ea\u5b9a\u4e49\u57df
gb.accessPermissions = \u8bbf\u95ee\u6743\u9650
gb.filters = \u8fc7\u6ee4
gb.filters = \u7b5b\u9009
gb.generalDescription = \u4e00\u822c\u8bbe\u7f6e
gb.accessPermissionsDescription = \u6309\u7167\u7528\u6237\u548c\u56e2\u961f\u9650\u5236\u8bbf\u95ee
gb.accessPermissionsForUserDescription = \u8bbe\u7f6e\u56e2\u961f\u6210\u5458\u6216\u8005\u6388\u4e88\u6307\u5b9a\u7248\u672c\u5e93\u6743\u9650
gb.accessPermissionsDescription = \u6309\u7167\u7528\u6237\u548c\u56e2\u961f\u8bbe\u7f6e\u8bbf\u95ee\u6743\u9650
gb.accessPermissionsForUserDescription = \u8bbe\u7f6e\u56e2\u961f\u6210\u5458\u6216\u6388\u4e88\u6307\u5b9a\u7248\u672c\u5e93\u6743\u9650
gb.accessPermissionsForTeamDescription = \u8bbe\u7f6e\u56e2\u961f\u6210\u5458\u5e76\u6388\u4e88\u6307\u5b9a\u7248\u672c\u5e93\u6743\u9650
gb.federationRepositoryDescription = \u4e0e\u5176\u4ed6Gitblit\u670d\u52a1\u5668\u5206\u4eab\u7248\u672c\u5e93
gb.hookScriptsDescription = \u5728\u670d\u52a1\u5668\u4e0a\u8fd0\u884cGroovy\u811a\u672c
gb.federationRepositoryDescription = \u4e0e\u5176\u4ed6 Gitblit \u670d\u52a1\u5668\u5206\u4eab\u7248\u672c\u5e93
gb.hookScriptsDescription = \u5728\u670d\u52a1\u5668\u4e0a\u8fd0\u884c Groovy \u811a\u672c
gb.reset = \u91cd\u7f6e

@@ -232,80 +230,80 @@ gb.pages = \u9875\u9762

gb.query = \u67e5\u8be2
gb.queryHelp = \u652f\u6301\u6807\u51c6\u67e5\u8be2\u683c\u5f0f.<p/><p/>\u8bf7\u67e5\u770b ${querySyntax} \u4ee5\u83b7\u53d6\u8be6\u7ec6\u5185\u5bb9\u3002
gb.queryHelp = \u652f\u6301\u6807\u51c6\u67e5\u8be2\u683c\u5f0f\u3002<p/><p/>\u8bf7\u53c2\u9605 ${querySyntax} \u4ee5\u8fdb\u4e00\u6b65\u4e86\u89e3\u3002
gb.querySyntax = Lucene \u67e5\u8be2\u5904\u7406\u5668\u683c\u5f0f
gb.queryResults = \u7ed3\u679c {0} - {1} ({2} \u6b21\u547d\u4e2d)
gb.noHits = \u672a\u547d\u4e2d
gb.authored = authored
gb.committed = committed
gb.authored = \u4f5c\u8005
gb.committed = \u5df2\u63d0\u4ea4
gb.indexedBranches = \u5df2\u7d22\u5f15\u5206\u652f
gb.indexedBranchesDescription = \u9009\u62e9\u8981\u653e\u5165\u60a8\u7684 Lucene \u7d22\u5f15\u7684\u5206\u652f
gb.noIndexedRepositoriesWarning = \u60a8\u7684\u6240\u6709\u7248\u672c\u5e93\u90fd\u6ca1\u6709\u7ecf\u8fc7 Lucene \u7d22\u5f15
gb.undefinedQueryWarning = \u67e5\u8be2\u672a\u5b9a\u4e49!
gb.noSelectedRepositoriesWarning = \u8bf7\u81f3\u5c11\u9009\u62e9\u4e00\u4e2a\u7248\u672c\u5e93!
gb.luceneDisabled = Lucene \u7d22\u5f15\u5df2\u88ab\u7981\u6b62
gb.undefinedQueryWarning = \u672a\u8bbe\u7f6e\u67e5\u8be2\u6761\u4ef6
gb.noSelectedRepositoriesWarning = \u8bf7\u81f3\u5c11\u9009\u62e9\u4e00\u4e2a\u7248\u672c\u5e93
gb.luceneDisabled = Lucene \u7d22\u5f15\u5df2\u7981\u7528
gb.failedtoRead = \u8bfb\u53d6\u5931\u8d25
gb.isNotValidFile = \u4e0d\u662f\u5408\u6cd5\u6587\u4ef6
gb.failedToReadMessage = \u5728 {0} \u4e2d\u8bfb\u53d6\u9ed8\u8ba4\u6d88\u606f\u5931\u8d25!
gb.passwordsDoNotMatch = \u5bc6\u7801\u4e0d\u5339\u914d!
gb.passwordTooShort = \u5bc6\u7801\u957f\u5ea6\u592a\u77ed\u3002\u6700\u77ed\u957f\u5ea6 {0} \u4e2a\u5b57\u7b26\u3002
gb.passwordChanged = \u5bc6\u7801\u4fee\u6539\u6210\u529f\u3002
gb.passwordChangeAborted = \u5bc6\u7801\u4fee\u6539\u7ec8\u6b62
gb.pleaseSetRepositoryName = \u8bf7\u8bbe\u7f6e\u4e00\u4e2a\u7248\u672c\u5e93\u540d\u79f0!
gb.isNotValidFile = \u4e0d\u662f\u6709\u6548\u6587\u4ef6
gb.failedToReadMessage = \u5728 {0} \u4e2d\u8bfb\u53d6\u9ed8\u8ba4\u6d88\u606f\u5931\u8d25
gb.passwordsDoNotMatch = \u5bc6\u7801\u4e0d\u5339\u914d
gb.passwordTooShort = \u5bc6\u7801\u957f\u5ea6\u592a\u77ed\uff0c\u6700\u77ed\u957f\u5ea6 {0} \u4e2a\u5b57\u7b26\u3002
gb.passwordChanged = \u5bc6\u7801\u5df2\u66f4\u6539\u3002
gb.passwordChangeAborted = \u5bc6\u7801\u66f4\u6539\u5df2\u53d6\u6d88\u3002
gb.pleaseSetRepositoryName = \u8bf7\u8bbe\u7f6e\u4e00\u4e2a\u7248\u672c\u5e93\u540d\u79f0
gb.illegalLeadingSlash = \u7981\u6b62\u4f7f\u7528\u6839\u76ee\u5f55\u5f15\u7528 (/) \u3002
gb.illegalRelativeSlash = \u76f8\u5bf9\u6587\u4ef6\u5939\u8def\u5f84(../)\u7981\u6b62\u4f7f\u7528
gb.illegalCharacterRepositoryName = \u7248\u672c\u5e93\u4e2d\u542b\u6709\u4e0d\u5408\u6cd5\u5b57\u7b26 ''{0}'' !
gb.selectAccessRestriction = \u8bf7\u9009\u62e9\u8bbf\u95ee\u6743\u9650\uff01
gb.selectFederationStrategy = \u8bf7\u9009\u62e9federation\u7b56\u7565!
gb.pleaseSetTeamName = \u8bf7\u8f93\u5165\u4e00\u4e2a\u56e2\u961f\u540d\u79f0\uff01
gb.illegalCharacterRepositoryName = \u7248\u672c\u5e93\u4e2d\u542b\u6709\u4e0d\u5408\u6cd5\u5b57\u7b26 ''{0}''
gb.selectAccessRestriction = \u8bf7\u9009\u62e9\u8bbf\u95ee\u6743\u9650
gb.selectFederationStrategy = \u8bf7\u9009\u62e9 federation \u7b56\u7565
gb.pleaseSetTeamName = \u8bf7\u8f93\u5165\u4e00\u4e2a\u56e2\u961f\u540d\u79f0
gb.teamNameUnavailable = \u56e2\u961f\u540d ''{0}'' \u4e0d\u5408\u6cd5.
gb.teamMustSpecifyRepository = \u56e2\u961f\u5fc5\u987b\u62e5\u6709\u81f3\u5c11\u4e00\u4e2a\u7248\u672c\u5e93\u3002
gb.teamCreated = \u6210\u529f\u521b\u5efa\u65b0\u56e2\u961f ''{0}'' .
gb.pleaseSetUsername = \u8bf7\u8f93\u5165\u7528\u6237\u540d\uff01
gb.usernameUnavailable = \u7528\u6237\u540d ''{0}'' \u4e0d\u53ef\u7528..
gb.combinedMd5Rename = Gitblit\u91c7\u7528\u6df7\u5408md5\u5bc6\u7801\u54c8\u5e0c\u3002\u56e0\u6b64\u5fc5\u987b\u5728\u4fee\u6539\u7528\u6237\u540d\u540e\u4fee\u6539\u5bc6\u7801\u3002
gb.userCreated = \u6210\u529f\u521b\u5efa\u65b0\u7528\u6237 \\"{0}\\"\u3002
gb.couldNotFindFederationRegistration = \u65e0\u6cd5\u627e\u5230federation registration!
gb.failedToFindGravatarProfile = \u52a0\u8f7d {0} \u7684Gravatar\u4fe1\u606f\u5931\u8d25
gb.pleaseSetUsername = \u8bf7\u8f93\u5165\u7528\u6237\u540d
gb.usernameUnavailable = \u7528\u6237\u540d ''{0}'' \u4e0d\u53ef\u7528
gb.combinedMd5Rename = Gitblit \u91c7\u7528\u6df7\u5408 MD5 \u5bc6\u7801\u54c8\u5e0c\uff0c\u56e0\u6b64\u5fc5\u987b\u5728\u4fee\u6539\u7528\u6237\u540d\u540e\u4fee\u6539\u5bc6\u7801\u3002
gb.userCreated = \u6210\u529f\u521b\u5efa\u65b0\u7528\u6237 \"{0}\"\u3002
gb.couldNotFindFederationRegistration = \u65e0\u6cd5\u627e\u5230 federation registration
gb.failedToFindGravatarProfile = \u52a0\u8f7d {0} \u7684 Gravatar \u4fe1\u606f\u5931\u8d25
gb.branchStats = {0} \u4e2a\u63d0\u4ea4\u548c {1} \u4e2a\u6807\u7b7e\u5728 {2} \u5185
gb.repositoryNotSpecified = \u672a\u6307\u5b9a\u7248\u672c\u5e93!
gb.repositoryNotSpecifiedFor = \u6ca1\u6709\u4e3a {0} \u8bbe\u7f6e\u7248\u672c\u5e93!
gb.repositoryNotSpecified = \u672a\u6307\u5b9a\u7248\u672c\u5e93
gb.repositoryNotSpecifiedFor = \u6ca1\u6709\u4e3a {0} \u8bbe\u7f6e\u7248\u672c\u5e93
gb.canNotLoadRepository = \u65e0\u6cd5\u8f7d\u5165\u7248\u672c\u5e93
gb.commitIsNull = \u63d0\u4ea4\u5185\u5bb9\u4e3a\u7a7a
gb.unauthorizedAccessForRepository = \u672a\u6388\u6743\u8bbf\u95ee\u7248\u672c\u5e93
gb.failedToFindCommit = \u5728 {1} \u4e2d {2} \u4e2a\u9875\u9762\u5185\u67e5\u627e\u63d0\u4ea4 \\"{0}\\"\u5931\u8d25!
gb.couldNotFindFederationProposal = \u65e0\u6cd5\u627e\u5230federation proposal!
gb.invalidUsernameOrPassword = \u7528\u6237\u540d\u6216\u8005\u5bc6\u7801\u9519\u8bef\uff01
gb.OneProposalToReview = 1\u4e2afederation proposals\u7b49\u5f85\u5ba1\u67e5\u3002
gb.nFederationProposalsToReview = {0} \u4e2afederation proposals\u7b49\u5f85\u5ba1\u67e5
gb.failedToFindCommit = \u5728 {1} \u4e2d {2} \u4e2a\u9875\u9762\u5185\u67e5\u627e\u63d0\u4ea4 \"{0}\"\u5931\u8d25
gb.couldNotFindFederationProposal = \u65e0\u6cd5\u627e\u5230 federation proposal
gb.invalidUsernameOrPassword = \u7528\u6237\u540d\u6216\u8005\u5bc6\u7801\u9519\u8bef
gb.OneProposalToReview = 1\u4e2a federation proposal \u9700\u8981\u5ba1\u67e5
gb.nFederationProposalsToReview = {0} \u4e2a federation proposals \u9700\u8981\u5ba1\u67e5
gb.couldNotFindTag = \u65e0\u6cd5\u627e\u5230\u6807\u7b7e {0}
gb.couldNotCreateFederationProposal = \u65e0\u6cd5\u521b\u5efafederation proposal!
gb.pleaseSetGitblitUrl = \u8bf7\u8f93\u5165\u4f60\u7684Gitblit\u7f51\u5740!
gb.pleaseSetDestinationUrl = \u8bf7\u4e3a\u4f60\u7684proposal\u8f93\u5165\u4e00\u4e2a\u76ee\u6807\u5730\u5740!
gb.proposalReceived = \u6210\u529f\u4ece {0} \u63a5\u6536Proposal.
gb.noGitblitFound = \u62b1\u6b49, {0} \u65e0\u6cd5\u5728{1} \u4e2d\u627e\u5230Gitblit\u5b9e\u4f8b\u3002
gb.noProposals = \u62b1\u6b49, {0} \u5f53\u524d\u4e0d\u63a5\u53d7proposals\u3002
gb.noFederation = \u62b1\u6b49, {0} \u6ca1\u6709\u4e0e\u4efb\u4f55Gitblit\u5b9e\u4f8b\u8bbe\u7f6efederate\u3002.
gb.proposalFailed = \u62b1\u6b49, {0} \u65e0\u6cd5\u63a5\u53d7\u4efb\u4f55proposal\u6570\u636e!
gb.proposalError = \u62b1\u6b49\uff0c{0} \u62a5\u544a\u4e2d\u53d1\u73b0\u672a\u9884\u671f\u7684\u9519\u8bef\uff01
gb.failedToSendProposal = \u53d1\u9001proposal\u5931\u8d25!
gb.userServiceDoesNotPermitAddUser = {0} \u4e0d\u5141\u8bb8\u6dfb\u52a0\u7528\u6237!
gb.userServiceDoesNotPermitPasswordChanges = {0} \u4e0d\u5141\u8bb8\u8fdb\u884c\u5bc6\u7801\u4fee\u6539!
gb.couldNotCreateFederationProposal = \u65e0\u6cd5\u521b\u5efa federation proposal
gb.pleaseSetGitblitUrl = \u8bf7\u8f93\u5165\u4f60\u7684 Gitblit URL
gb.pleaseSetDestinationUrl = \u8bf7\u4e3a\u4f60\u7684 proposal \u8f93\u5165\u4e00\u4e2a\u76ee\u6807 URL
gb.proposalReceived = \u6210\u529f\u4ece {0} \u63a5\u6536 Proposal
gb.noGitblitFound = \u62b1\u6b49, {0} \u65e0\u6cd5\u5728 {1} \u4e2d\u627e\u5230 Gitblit \u5b9e\u4f8b\u3002
gb.noProposals = \u62b1\u6b49, {0} \u5f53\u524d\u4e0d\u63a5\u53d7 proposals\u3002
gb.noFederation = \u62b1\u6b49, {0} \u6ca1\u6709\u4e0e\u4efb\u4f55 Gitblit \u5b9e\u4f8b\u8bbe\u7f6e federate\u3002
gb.proposalFailed = \u62b1\u6b49, {0} \u65e0\u6cd5\u63a5\u53d7\u4efb\u4f55 proposal \u6570\u636e\u3002
gb.proposalError = \u62b1\u6b49\uff0c{0} \u62a5\u544a\u4e2d\u53d1\u73b0\u672a\u77e5\u9519\u8bef\u3002
gb.failedToSendProposal = \u53d1\u9001 proposal \u5931\u8d25
gb.userServiceDoesNotPermitAddUser = {0} \u4e0d\u5141\u8bb8\u6dfb\u52a0\u7528\u6237
gb.userServiceDoesNotPermitPasswordChanges = {0} \u4e0d\u5141\u8bb8\u4fee\u6539\u5bc6\u7801
gb.displayName = \u663e\u793a\u540d\u79f0
gb.emailAddress = \u90ae\u7bb1
gb.errorAdminLoginRequired = \u9700\u8981\u7ba1\u7406\u5458\u767b\u9646
gb.emailAddress = \u7535\u5b50\u90ae\u4ef6\u5730\u5740
gb.errorAdminLoginRequired = \u9700\u8981\u4ee5\u7ba1\u7406\u5458\u8eab\u4efd\u767b\u5f55
gb.errorOnlyAdminMayCreateRepository = \u53ea\u6709\u7ba1\u7406\u5458\u624d\u53ef\u4ee5\u521b\u5efa\u7248\u672c\u5e93
gb.errorOnlyAdminOrOwnerMayEditRepository = \u53ea\u6709\u7ba1\u7406\u5458\u6216\u8005\u6240\u6709\u8005\u624d\u53ef\u4ee5\u7f16\u8f91\u4ee3\u7801\u5e93
gb.errorAdministrationDisabled = \u7ba1\u7406\u6743\u9650\u88ab\u7981\u6b62\u3002
gb.errorOnlyAdminOrOwnerMayEditRepository = \u53ea\u6709\u7ba1\u7406\u5458\u6216\u8005\u6240\u6709\u8005\u624d\u53ef\u4ee5\u7f16\u8f91\u7248\u672c\u5e93
gb.errorAdministrationDisabled = \u7ba1\u7406\u6743\u9650\u88ab\u7981\u6b62
gb.lastNDays = \u6700\u8fd1 {0} \u5929
gb.completeGravatarProfile = \u5728Gravatar.com\u4e0a\u5b8c\u6210\u4e2a\u4eba\u8bbe\u5b9a
gb.completeGravatarProfile = \u5728 Gravatar.com \u4e0a\u7f16\u8f91\u4e2a\u4eba\u8d44\u6599
gb.none = \u65e0
gb.line = \u884c
gb.content = \u5185\u5bb9
gb.empty = \u7a7a\u767d\u7248\u672c\u5e93
gb.empty = \u7a7a\u7248\u672c\u5e93
gb.inherited = \u7ee7\u627f
gb.deleteRepository = \u5220\u9664\u7248\u672c\u5e93 \\"{0}\\" \uff1f
gb.deleteRepository = \u5220\u9664\u7248\u672c\u5e93 \"{0}\" \uff1f
gb.repositoryDeleted = \u7248\u672c\u5e93 ''{0}'' \u5df2\u5220\u9664\u3002
gb.repositoryDeleteFailed = \u5220\u9664\u7248\u672c\u5e93 \\"{0}\\" \u5931\u8d25\uff01
gb.deleteUser = \u5220\u9664\u7528\u6237 \\"{0}\\" \uff1f
gb.userDeleted = \u7528\u6237 ''{0}'' \u5df2\u5220\u9664\uff01
gb.userDeleteFailed = \u5220\u9664\u7528\u6237''{0}''\u5931\u8d25\uff01
gb.repositoryDeleteFailed = \u5220\u9664\u7248\u672c\u5e93 \"{0}\" \u5931\u8d25\u3002
gb.deleteUser = \u5220\u9664\u7528\u6237 \"{0}\" \uff1f
gb.userDeleted = \u7528\u6237 ''{0}'' \u5df2\u5220\u9664\u3002
gb.userDeleteFailed = \u5220\u9664\u7528\u6237''{0}''\u5931\u8d25\u3002
gb.time.justNow = \u521a\u521a

@@ -330,3 +328,3 @@ gb.time.today = \u4eca\u5929

gb.allowNamedDescription = \u6388\u4e88\u6307\u5b9a\u540d\u79f0\u7684\u7528\u6237\u6216\u56e2\u961f\u53d7\u9650\u7684\u8bbf\u95ee\u6743\u9650
gb.markdownFailure = \u8bfb\u53d6 Markdown \u5185\u5bb9\u5931\u8d25\uff01
gb.markdownFailure = \u8bfb\u53d6 Markdown \u5185\u5bb9\u5931\u8d25\u3002
gb.clearCache = \u6e05\u9664\u7f13\u5b58

@@ -337,27 +335,27 @@ gb.projects = \u9879\u76ee

gb.copyToClipboard = \u590d\u5236\u5230\u526a\u8d34\u677f
gb.fork = \u6d3e\u751f
gb.forks = \u6d3e\u751f
gb.forkRepository = \u6d3e\u751f {0} ?
gb.repositoryForked = {0} \u5df2\u88ab\u6d3e\u751f
gb.repositoryForkFailed = \u6d3e\u751f\u5931\u8d25
gb.personalRepositories = \u79c1\u4eba\u7248\u672c\u5e93
gb.allowForks = \u5141\u8bb8\u6d3e\u751f
gb.allowForksDescription = \u5141\u8bb8\u8ba4\u8bc1\u7528\u6237\u6d3e\u751f\u6b64\u7248\u672c\u5e93
gb.forkedFrom = \u6d3e\u751f\u81ea
gb.canFork = \u5141\u8bb8\u6d3e\u751f
gb.canForkDescription = \u5141\u8bb8\u6d3e\u751f\u8ba4\u8bc1\u7248\u672c\u5e93\u5230\u79c1\u4eba\u7248\u672c\u5e93
gb.myFork = \u67e5\u770b\u6211\u7684\u6d3e\u751f
gb.forksProhibited = \u7981\u6b62\u6d3e\u751f
gb.forksProhibitedWarning = \u5f53\u524d\u7248\u672c\u5e93\u7981\u6b62\u6d3e\u751f
gb.noForks = {0} \u6ca1\u6709\u6d3e\u751f
gb.forkNotAuthorized = \u62b1\u6b49\uff0c\u60a8\u65e0\u6743\u6d3e\u751f {0}
gb.forkInProgress = \u6b63\u5728\u6d3e\u751f
gb.preparingFork = \u6b63\u5728\u4e3a\u60a8\u51c6\u5907\u6d3e\u751f...
gb.isFork = \u5df2\u6d3e\u751f
gb.fork = \u5efa\u7acb\u5206\u652f
gb.forks = \u5206\u652f
gb.forkRepository = \u5efa\u7acb {0} \u7684\u5206\u652f\uff1f
gb.repositoryForked = {0} \u5df2\u5efa\u7acb\u5206\u652f
gb.repositoryForkFailed = \u5efa\u7acb\u5206\u652f\u5931\u8d25
gb.personalRepositories = \u79c1\u6709\u7248\u672c\u5e93
gb.allowForks = \u5141\u8bb8\u5efa\u7acb\u5206\u652f
gb.allowForksDescription = \u5141\u8bb8\u6388\u6743\u7684\u7528\u6237\u5efa\u7acb\u6b64\u7248\u672c\u5e93\u7684\u5206\u652f
gb.forkedFrom = \u5206\u652f\u81ea
gb.canFork = \u5141\u8bb8\u5206\u652f
gb.canForkDescription = \u5141\u8bb8\u5206\u652f\u7248\u672c\u5e93\u5e76\u590d\u5236\u5230\u79c1\u6709\u7248\u672c\u5e93\u4e2d
gb.myFork = \u67e5\u770b\u6211\u7684\u5206\u652f
gb.forksProhibited = \u7981\u6b62\u5efa\u7acb\u5206\u652f
gb.forksProhibitedWarning = \u5f53\u524d\u7248\u672c\u5e93\u7981\u6b62\u5efa\u7acb\u5206\u652f
gb.noForks = {0} \u6ca1\u6709\u5206\u652f
gb.forkNotAuthorized = \u62b1\u6b49\uff0c\u60a8\u65e0\u6743\u5206\u652f {0}
gb.forkInProgress = \u6b63\u5728\u590d\u5236
gb.preparingFork = \u6b63\u5728\u4e3a\u60a8\u51c6\u5907\u5206\u652f...
gb.isFork = \u5df2\u5efa\u7acb\u5206\u652f
gb.canCreate = \u5141\u8bb8\u521b\u5efa
gb.canCreateDescription = \u5141\u8bb8\u521b\u5efa\u79c1\u4eba\u7248\u672c\u5e93
gb.illegalPersonalRepositoryLocation = \u60a8\u7684\u79c1\u4eba\u7248\u672c\u5e93\u5fc5\u987b\u4f4d\u4e8e \\"{0}\\"
gb.canCreateDescription = \u5141\u8bb8\u521b\u5efa\u79c1\u6709\u7248\u672c\u5e93
gb.illegalPersonalRepositoryLocation = \u60a8\u7684\u79c1\u6709\u7248\u672c\u5e93\u5fc5\u987b\u4f4d\u4e8e \"{0}\"
gb.verifyCommitter = \u9a8c\u8bc1\u63d0\u4ea4\u8005
gb.verifyCommitterDescription = \u9700\u8981\u63d0\u4ea4\u8005\u7684\u8eab\u4efd\u4e0e Gitblit \u7528\u6237\u8eab\u4efd\u76f8\u7b26
gb.verifyCommitterNote = \u6240\u6709\u5408\u5e76\u9009\u9879\u9700\u8981\u4f7f\u7528 \\"--no-ff\\" \u6765\u6267\u884c\u63d0\u4ea4\u8005\u9a8c\u8bc1
gb.verifyCommitterNote = \u6240\u6709\u5408\u5e76\u9009\u9879\u9700\u8981\u4f7f\u7528 \"--no-ff\" \u6765\u6267\u884c\u63d0\u4ea4\u8005\u9a8c\u8bc1
gb.repositoryPermissions = \u7248\u672c\u5e93\u6743\u9650

@@ -367,12 +365,11 @@ gb.userPermissions = \u7528\u6237\u6743\u9650

gb.add = \u6dfb\u52a0
gb.noPermission = \u5220\u9664\u6b64\u6743\u9650
gb.excludePermission = {0} (\u6392\u9664)
gb.viewPermission = {0} (\u6d4f\u89c8)
gb.clonePermission = {0} (\u514b\u9686)
gb.pushPermission = {0} (\u63a8\u9001)
gb.createPermission = {0} (\u63a8\u9001, \u521b\u5efaref)
gb.deletePermission = {0} (\u63a8\u9001, \u521b\u5efa\u5220\u9664ref)
gb.rewindPermission = {0} (\u63a8\u9001, \u521b\u5efa\u5220\u9664\u4ee5\u53carewind ref)
gb.permission = \u6743\u9650
gb.regexPermission = \u6b64\u6743\u9650\u662f\u901a\u8fc7\u6b63\u5219\u8868\u8fbe\u5f0f \\"{0}\\" \u8bbe\u7f6e
gb.noPermission = \u64a4\u9500\u6b64\u6743\u9650
gb.excludePermission = {0}\uff08\u6392\u9664\uff09
gb.viewPermission = {0}\uff08\u6d4f\u89c8\uff09
gb.clonePermission = {0}\uff08\u514b\u9686\uff09
gb.pushPermission = {0}\uff08\u63a8\u9001\uff09
gb.createPermission = {0}\uff08\u63a8\u9001, \u521b\u5efa\uff0c\u5f15\u7528\uff09
gb.deletePermission = {0}\uff08\u63a8\u9001, \u521b\u5efa\uff0c\u5220\u9664\uff0c\u5f15\u7528\uff09
gb.rewindPermission = {0}\uff08\u63a8\u9001, \u521b\u5efa\uff0c\u5220\u9664\uff0c\u56de\u9000\uff09
gb.regexPermission = \u6b64\u6743\u9650\u662f\u901a\u8fc7\u6b63\u5219\u8868\u8fbe\u5f0f \"{0}\" \u8bbe\u7f6e
gb.accessDenied = \u8bbf\u95ee\u88ab\u62d2\u7edd

@@ -383,14 +380,14 @@ gb.busyCollectingGarbage = \u62b1\u6b49\uff0cGitblit\u6b63\u5728 {0} \u5185\u6e05\u7406\u5783\u573e

gb.gcThreshold = \u5783\u573e\u6e05\u7406\u9600\u503c
gb.gcThresholdDescription = \u6fc0\u53d1\u5783\u573e\u6e05\u7406\u7684\u6700\u5c0f\u5bf9\u8c61\u5927\u5c0f
gb.ownerPermission = \u7248\u672c\u5e93\u521b\u5efa\u8005
gb.gcThresholdDescription = \u89e6\u53d1\u5783\u573e\u6e05\u7406\u7684\u6700\u5c0f\u5bf9\u8c61\u5927\u5c0f
gb.ownerPermission = \u7248\u672c\u5e93\u6240\u6709\u8005
gb.administrator = \u7ba1\u7406\u5458
gb.administratorPermission = Gitblit \u7ba1\u7406\u5458
gb.team = \u56e2\u961f
gb.teamPermission = \u901a\u8fc7 \\"{0}\\" \u56e2\u961f\u6210\u5458\u8bbe\u7f6e\u6743\u9650
gb.missing = \u4e0d\u5b58\u5728!
gb.missingPermission = \u6b64\u6743\u9650\u7684\u7248\u672c\u5e93\u4e0d\u5b58\u5728!
gb.mutable = mutable
gb.specified = specified
gb.effective = effective
gb.organizationalUnit = \u7ec4\u7ec7\u5355\u5143
gb.teamPermission = \u901a\u8fc7 \"{0}\" \u56e2\u961f\u6210\u5458\u8bbe\u7f6e\u6743\u9650
gb.missing = \u4e0d\u5b58\u5728
gb.missingPermission = \u6b64\u6743\u9650\u65e0\u6cd5\u5bf9\u5e94\u5230\u7248\u672c\u5e93
gb.mutable = \u53ef\u53d8\u7684
gb.specified = \u6307\u5b9a\u7684
gb.effective = \u6709\u6548\u7684
gb.organizationalUnit = \u7ec4\u7ec7\u5355\u4f4d
gb.organization = \u7ec4\u7ec7

@@ -413,4 +410,4 @@ gb.locality = \u5730\u533a

gb.ok = \u786e\u5b9a
gb.invalidExpirationDate = \u65e0\u6548\u7684\u8fc7\u671f\u65f6\u95f4!
gb.passwordHintRequired = \u9700\u8981\u586b\u5199\u5bc6\u7801\u63d0\u793a!
gb.invalidExpirationDate = \u65e0\u6548\u7684\u8fc7\u671f\u65f6\u95f4
gb.passwordHintRequired = \u9700\u8981\u586b\u5199\u5bc6\u7801\u63d0\u793a
gb.viewCertificate = \u67e5\u770b\u8bc1\u4e66

@@ -428,5 +425,5 @@ gb.subject = \u4e3b\u9898

gb.unspecified = \u672a\u6307\u5b9a
gb.keyCompromise = key compromise
gb.caCompromise = CA compromise
gb.affiliationChanged = \u96b6\u5c5e\u5173\u7cfb\u5df2\u4fee\u6539
gb.keyCompromise = \u5bc6\u94a5\u6cc4\u9732
gb.caCompromise = CA \u6cc4\u9732
gb.affiliationChanged = \u96b6\u5c5e\u5173\u7cfb\u5df2\u66f4\u6539
gb.superseded = \u5df2\u53d6\u4ee3

@@ -446,10 +443,10 @@ gb.cessationOfOperation = \u505c\u6b62\u64cd\u4f5c

gb.sslCertificateGenerated = \u6210\u529f\u4e3a {0} \u751f\u6210\u65b0\u7684\u670d\u52a1\u5668 SSL \u8bc1\u4e66
gb.newClientCertificateMessage = \u6ce8\u610f:\\n\u6b64\u5bc6\u7801\u5e76\u975e\u7528\u6237\u5bc6\u7801, \u8fd9\u662f\u4fdd\u5b58\u7528\u6237 keystore \u7684\u5bc6\u7801\u3002 \u7531\u4e8e\u672c\u5bc6\u7801\u672a\u5b58\u50a8\uff0c\u56e0\u6b64\u4f60\u5fc5\u987b\u4e00\u4e2a\u5bc6\u7801\u63d0\u793a\uff0c\u8fd9\u4e2a\u63d0\u793a\u4f1a\u8bb0\u5f55\u5728\u7528\u6237\u7684 README \u6587\u6863\u5185\u3002
gb.newClientCertificateMessage = \u6ce8\u610f:\n\u6b64\u5bc6\u7801\u5e76\u975e\u7528\u6237\u5bc6\u7801, \u8fd9\u662f\u4fdd\u5b58\u7528\u6237 keystore \u7684\u5bc6\u7801\u3002 \u7531\u4e8e\u672c\u5bc6\u7801\u672a\u5b58\u50a8\uff0c\u56e0\u6b64\u4f60\u5fc5\u987b\u4e00\u4e2a\u5bc6\u7801\u63d0\u793a\uff0c\u8fd9\u4e2a\u63d0\u793a\u4f1a\u8bb0\u5f55\u5728\u7528\u6237\u7684 README \u6587\u6863\u5185\u3002
gb.certificate = \u8bc1\u4e66
gb.emailCertificateBundle = \u53d1\u9001\u5ba2\u6237\u7aef\u8bc1\u4e66
gb.pleaseGenerateClientCertificate = \u8bf7\u4e3a {0} \u751f\u6210\u4e00\u4e2a\u5ba2\u6237\u7aef\u8bc1\u4e66
gb.clientCertificateBundleSent = {0} \u7684\u5ba2\u6237\u7aef\u8bc1\u4e66\u5df2\u53d1\u9001
gb.clientCertificateBundleSent = \u5df2\u53d1\u9001 {0} \u7684\u5ba2\u6237\u7aef\u8bc1\u4e66
gb.enterKeystorePassword = \u8bf7\u8f93\u5165 Gitblit keystore \u5bc6\u7801
gb.warning = \u8b66\u544a
gb.jceWarning = \u60a8\u7684 JAVA \u8fd0\u884c\u73af\u5883\u4e0d\u5305\u542b \\"JCE Unlimited Strength Jurisdiction Policy\\" \u6587\u4ef6\u3002\\n\u8fd9\u5c06\u5bfc\u81f4\u60a8\u6700\u591a\u53ea\u80fd\u75287\u4e2a\u5b57\u7b26\u7684\u5bc6\u7801\u4fdd\u62a4\u60a8\u7684 keystore\u3002 \\n\u8fd9\u4e9b\u662f\u4e00\u4e9b\u53ef\u9009\u4e0b\u8f7d\u7684\u653f\u7b56\u6587\u4ef6\u3002\\n\\n\u4f60\u662f\u5426\u8981\u7ee7\u7eed\u751f\u6210\u8bc1\u4e66\uff1f\\n\\n\u9009\u62e9\u5426\u7684\u8bdd\uff0c\u5c06\u4f1a\u6253\u5f00\u4e00\u4e2a\u6d4f\u89c8\u5668\u754c\u9762\u4f9b\u60a8\u4e0b\u8f7d\u76f8\u5173\u6587\u4ef6\u3002
gb.jceWarning = \u60a8\u7684 JAVA \u8fd0\u884c\u73af\u5883\u4e0d\u5305\u542b \"JCE Unlimited Strength Jurisdiction Policy\" \u6587\u4ef6\u3002\n\u8fd9\u5c06\u5bfc\u81f4\u60a8\u6700\u591a\u53ea\u80fd\u7528 7 \u4e2a\u5b57\u7b26\u7684\u5bc6\u7801\u4fdd\u62a4\u60a8\u7684 keystore\u3002 \n\u8fd9\u4e9b\u662f\u4e00\u4e9b\u53ef\u9009\u4e0b\u8f7d\u7684\u6587\u4ef6\u3002\n\n\u4f60\u662f\u5426\u8981\u7ee7\u7eed\u751f\u6210\u8bc1\u4e66\uff1f\n\n\u9009\u62e9\u5426\u7684\u8bdd\uff0c\u5c06\u4f1a\u6253\u5f00\u4e00\u4e2a\u6d4f\u89c8\u5668\u9875\u9762\u4f9b\u60a8\u4e0b\u8f7d\u76f8\u5173\u6587\u4ef6\u3002
gb.maxActivityCommits = \u6700\u5927\u6d3b\u52a8\u63d0\u4ea4\u6570

@@ -460,4 +457,4 @@ gb.maxActivityCommitsDescription = \u6d3b\u52a8\u9875\u9762\u663e\u793a\u7684\u6700\u5927\u63d0\u4ea4\u6570

gb.serveCertificate = \u4f7f\u7528\u6b64\u8bc1\u4e66\u63d0\u4f9b https \u652f\u6301
gb.sslCertificateGeneratedRestart = \u6210\u529f\u4e3a {0} \u751f\u6210\u65b0\u7684 SSL \u8bc1\u4e66.\\n\u4f60\u5fc5\u987b\u91cd\u65b0\u542f\u52a8 Gitblit \u4ee5\u4f7f\u7528\u6b64\u8bc1\u4e66\u3002\\n\\n\u5982\u679c\u60a8\u4f7f\u7528 '--alias' \u53c2\u6570\u542f\u52a8\uff0c\u4f60\u5fc5\u987b\u4e5f\u8981\u8bbe\u7f6e ''--alias {0}''\u3002
gb.validity = \u5408\u6cd5\u6027
gb.sslCertificateGeneratedRestart = \u6210\u529f\u4e3a {0} \u751f\u6210\u65b0\u7684 SSL \u8bc1\u4e66.\n\u4f60\u5fc5\u987b\u91cd\u65b0\u542f\u52a8 Gitblit \u4ee5\u4f7f\u7528\u6b64\u8bc1\u4e66\u3002\n\n\u5982\u679c\u60a8\u4f7f\u7528 '--alias' \u53c2\u6570\u542f\u52a8\uff0c\u4f60\u5fc5\u987b\u4e5f\u8981\u8bbe\u7f6e ''--alias {0}''\u3002
gb.validity = \u6709\u6548\u6027
gb.siteName = \u7f51\u7ad9\u540d\u79f0

@@ -467,3 +464,3 @@ gb.siteNameDescription = \u60a8\u7684\u670d\u52a1\u5668\u7684\u7b80\u8981\u63cf\u8ff0

gb.isSparkleshared = \u7248\u672c\u5e93\u5df2\u901a\u8fc7 Sparkleshare \u5b8c\u6210\u540c\u6b65
gb.owners = \u62e5\u6709\u8005
gb.owners = \u6240\u6709\u8005
gb.sessionEnded = \u4f1a\u8bdd\u5df2\u5173\u95ed

@@ -475,16 +472,16 @@ gb.closeBrowser = \u8bf7\u5173\u95ed\u6d4f\u89c8\u5668\u4ee5\u4fbf\u6b63\u5e38\u5173\u95ed\u4f1a\u8bdd\u3002

gb.incrementalPushTagMessage = \u63a8\u9001\u65f6\u81ea\u52a8\u4e3a\u5206\u652f [{0}] \u6dfb\u52a0\u6807\u7b7e
gb.externalPermissions = {0} \u7684\u8bbf\u95ee\u6743\u9650\u5c5e\u4e8e\u5916\u90e8\u63a7\u5236
gb.viewAccess = \u60a8\u6ca1\u6709 Gitblit \u8bfb\u6216\u5199\u7684\u6743\u9650
gb.overview = \u603b\u89c8
gb.dashboard = \u516c\u544a\u677f
gb.externalPermissions = {0} \u7684\u8bbf\u95ee\u6743\u9650\u7531\u5916\u90e8\u63a7\u5236
gb.viewAccess = \u60a8\u6ca1\u6709 Gitblit \u8bfb\u53d6\u6216\u5199\u5165\u7684\u6743\u9650
gb.overview = \u6982\u89c8
gb.dashboard = \u4eea\u8868\u76d8
gb.monthlyActivity = \u6bcf\u6708\u6d3b\u52a8
gb.myProfile = \u7528\u6237\u4e2d\u5fc3
gb.myProfile = \u4e2a\u4eba\u8d44\u6599
gb.compare = \u5bf9\u6bd4
gb.manual = \u624b\u518c
gb.from = from
gb.to = to
gb.at = at
gb.from = \u4ece
gb.to = \u81f3
gb.at = \u4e8e
gb.of = of
gb.in = in
gb.moreChanges = \u6240\u6709\u53d8\u52a8...
gb.moreChanges = \u6240\u6709\u53d8\u66f4...
gb.pushedNCommitsTo = \u5df2\u63a8\u9001 {0} \u6b21\u81f3

@@ -505,5 +502,5 @@ gb.pushedOneCommitTo = \u5df2\u63a8\u9001 1 \u6b21\u81f3

gb.deletedBranch = \u5df2\u5220\u9664\u5206\u652f
gb.createdNewPullRequest = \u521b\u5efa pull request
gb.mergedPullRequest = \u5408\u5e76 pull request
gb.rewind = REWIND
gb.createdNewPullRequest = \u521b\u5efa\u62c9\u53d6\u8bf7\u6c42
gb.mergedPullRequest = \u5408\u5e76\u62c9\u53d6\u8bf7\u6c42
gb.rewind = \u56de\u9000
gb.star = \u5173\u6ce8

@@ -513,14 +510,14 @@ gb.unstar = \u53d6\u6d88\u5173\u6ce8

gb.starredRepositories = \u5df2\u5173\u6ce8\u7248\u672c\u5e93
gb.failedToUpdateUser = \u66f4\u65b0\u7528\u6237\u8d26\u6237\u4fe1\u606f\u5931\u8d25!
gb.failedToUpdateUser = \u66f4\u65b0\u7528\u6237\u4fe1\u606f\u5931\u8d25
gb.myRepositories = \u6211\u7684\u7248\u672c\u5e93
gb.noActivity = \u6700\u8fd1 {0} \u5929\u5185\u6ca1\u6709\u4efb\u4f55\u6d3b\u52a8
gb.findSomeRepositories = \u5bfb\u627e\u7248\u672c\u5e93
gb.metricAuthorExclusions = author metric exclusions
gb.myDashboard = \u6211\u7684\u516c\u544a\u677f
gb.failedToFindAccount = \u5bfb\u627e\u8d26\u6237 ''{0}'' \u5931\u8d25
gb.metricAuthorExclusions = \u7edf\u8ba1\u65f6\u6392\u9664\u6d3b\u8dc3\u8d26\u6237
gb.myDashboard = \u6211\u7684\u4eea\u8868\u76d8
gb.failedToFindAccount = \u672a\u627e\u5230\u8d26\u6237 ''{0}''
gb.reflog = \u64cd\u4f5c\u8bb0\u5f55
gb.active = \u6d3b\u52a8
gb.starred = \u5df2\u5173\u6ce8
gb.owned = \u62e5\u6709\u7740
gb.starredAndOwned = \u5df2\u5173\u6ce8 & \u62e5\u6709\u7740
gb.owned = \u62e5\u6709
gb.starredAndOwned = \u5df2\u5173\u6ce8 & \u6240\u6709
gb.reviewPatchset = \u4fee\u8ba2 {0} \u8865\u4e01\u96c6 {1}

@@ -534,3 +531,3 @@ gb.todaysActivityStats = \u4eca\u5929 / \u6765\u81ea {2} \u7684 {1} \u6b21\u63d0\u4ea4

gb.home = \u4e3b\u9875
gb.isMirror = \u5f53\u524d\u7248\u672c\u662f\u4e00\u4e2a\u955c\u50cf
gb.isMirror = \u5f53\u524d\u7248\u672c\u5e93\u662f\u955c\u50cf
gb.mirrorOf = {0} \u7684\u955c\u50cf

@@ -540,5 +537,5 @@ gb.mirrorWarning = \u5f53\u524d\u7248\u672c\u5e93\u662f\u955c\u50cf\uff0c\u65e0\u6cd5\u63a5\u53d7\u63a8\u9001

gb.docsWelcome2 = \u63d0\u4ea4\u4e00\u4e2a README.md \u6216\u8005\u4e00\u4e2a HOME.md \u6765\u5f00\u59cb\u3002
gb.createReadme = \u521b\u5efa\u4e00\u4e2a README
gb.createReadme = \u521b\u5efa\u4e00\u4e2a README \u6587\u4ef6
gb.responsible = \u8d1f\u8d23\u4eba
gb.createdThisTicket = \u521b\u5efa\u5f53\u524d\u5de5\u5355
gb.createdThisTicket = \u521b\u5efa\u5f53\u524d\u4efb\u52a1
gb.proposedThisChange = \u63d0\u4ea4\u5f53\u524d\u4fee\u6539

@@ -550,3 +547,3 @@ gb.uploadedPatchsetN = \u4e0a\u4f20\u8865\u4e01\u96c6 {0}

gb.noDescriptionGiven = \u65e0\u63cf\u8ff0
gb.toBranch = \u5230 {0}
gb.toBranch = \u5230\u5206\u652f {0}
gb.createdBy = \u521b\u5efa\u8005

@@ -560,4 +557,4 @@ gb.oneParticipant = {0} \u4e2a\u53c2\u4e0e\u8005

gb.nAttachments = {0} \u4e2a\u9644\u4ef6
gb.milestone = milestone
gb.compareToMergeBase = \u4e0e\u5408\u5e76base\u5bf9\u6bd4
gb.milestone = \u91cc\u7a0b\u7891
gb.compareToMergeBase = \u548c merge base \u5bf9\u6bd4
gb.compareToN = \u548c {0} \u5bf9\u6bd4

@@ -567,11 +564,11 @@ gb.open = \u5f00\u542f

gb.merged = \u5df2\u5408\u5e76
gb.ticketPatchset = \u5de5\u5355 {0}, \u8865\u4e01\u96c6 {1}
gb.ticketPatchset = \u4efb\u52a1 {0}, \u8865\u4e01\u96c6 {1}
gb.patchsetMergeable = \u5f53\u524d\u8865\u4e01\u96c6\u53ef\u4ee5\u88ab\u81ea\u52a8\u5408\u5e76\u81f3 {0}\u3002
gb.patchsetMergeableMore = \u5f53\u524d\u8865\u4e01\u96c6\u4e5f\u53ef\u4ee5\u7528\u547d\u4ee4\u884c\u5408\u5e76\u81f3 {0} \u3002
gb.patchsetAlreadyMerged = \u5f53\u524d\u8865\u4e01\u96c6\u5df2\u88ab\u5408\u5e76\u81f3 {0}.
gb.patchsetNotMergeable = \u5f53\u524d\u8865\u4e01\u96c6\u65e0\u6cd5\u88ab\u81ea\u52a8\u5408\u5e76\u81f3 {0}.
gb.patchsetNotMergeableMore = \u5f53\u524d\u8865\u4e01\u96c6\u5fc5\u987brebase\u6216\u8005\u624b\u52a8\u5408\u5e76\u81f3 {0} \u4ee5\u89e3\u51b3\u51b2\u7a81\u3002
gb.patchsetMergeableMore = \u5f53\u524d\u8865\u4e01\u96c6\u4e5f\u53ef\u4ee5\u7528\u547d\u4ee4\u884c\u5408\u5e76\u81f3 {0}\u3002
gb.patchsetAlreadyMerged = \u5f53\u524d\u8865\u4e01\u96c6\u5df2\u88ab\u5408\u5e76\u81f3 {0}\u3002
gb.patchsetNotMergeable = \u5f53\u524d\u8865\u4e01\u96c6\u65e0\u6cd5\u88ab\u81ea\u52a8\u5408\u5e76\u81f3 {0}\u3002
gb.patchsetNotMergeableMore = \u5f53\u524d\u8865\u4e01\u96c6\u5fc5\u987b\u53d8\u57fa (rebase) \u6216\u8005\u624b\u52a8\u5408\u5e76\u81f3 {0} \u4ee5\u89e3\u51b3\u51b2\u7a81\u3002
gb.patchsetNotApproved = \u5f53\u524d\u8865\u4e01\u96c6\u672a\u88ab\u5141\u8bb8\u5408\u5e76\u81f3 {0}\u3002
gb.patchsetNotApprovedMore = \u5fc5\u987b\u6709\u4fee\u8ba2\u8005\u786e\u8ba4\u6b64\u8865\u4e01\u96c6\u3002
gb.patchsetVetoedMore = \u5df2\u6709\u4fee\u8ba2\u8005\u62d2\u7edd\u4e86\u6b64\u8865\u4e01\u96c6.
gb.patchsetNotApprovedMore = \u5fc5\u987b\u6709\u4fee\u8ba2\u8005\u6279\u51c6\u6b64\u8865\u4e01\u96c6\u3002
gb.patchsetVetoedMore = \u5df2\u6709\u4fee\u8ba2\u8005\u62d2\u7edd\u6b64\u8865\u4e01\u96c6\u3002
gb.write = \u64b0\u5199

@@ -584,6 +581,6 @@ gb.comment = \u8bc4\u8bba

gb.acceptNewPatchsetsDescription = \u63a5\u53d7\u63a8\u9001\u5230\u5f53\u524d\u7248\u672c\u5e93\u7684\u8865\u4e01\u96c6
gb.acceptNewTickets = \u5141\u8bb8\u521b\u5efa\u5de5\u5355
gb.acceptNewTicketsDescription = \u5141\u8bb8\u521b\u5efa\u5173\u4e8ebug, \u6539\u8fdb, \u4efb\u52a1\u76f8\u5173\u7684\u5de5\u5355
gb.requireApproval = \u9700\u8981\u786e\u8ba4
gb.requireApprovalDescription = \u5408\u5e76\u6309\u94ae\u53ea\u6709\u5728\u8865\u4e01\u96c6\u88ab\u786e\u8ba4\u540e\u624d\u4f1a\u88ab\u6fc0\u6d3b
gb.acceptNewTickets = \u5141\u8bb8\u521b\u5efa\u4efb\u52a1
gb.acceptNewTicketsDescription = \u5141\u8bb8\u521b\u5efa\u5173\u4e8e bug\uff0c\u6539\u8fdb\uff0c\u4efb\u52a1\u76f8\u5173\u7684\u4efb\u52a1
gb.requireApproval = \u9700\u8981\u6279\u51c6
gb.requireApprovalDescription = \u5408\u5e76\u6309\u94ae\u53ea\u6709\u5728\u8865\u4e01\u96c6\u88ab\u6279\u51c6\u540e\u624d\u53ef\u7528
gb.topic = \u4e3b\u9898

@@ -612,14 +609,14 @@ gb.proposalTickets = \u5df2\u53d1\u5e03\u5efa\u8bae

gb.topicsAndLabels = \u4e3b\u9898\u4e0e\u6807\u7b7e
gb.milestones = milestones
gb.noMilestoneSelected = \u6ca1\u6709\u88ab\u9009\u4e2d\u7684milestone
gb.milestones = \u91cc\u7a0b\u7891
gb.noMilestoneSelected = \u6ca1\u6709\u88ab\u9009\u4e2d\u7684\u91cc\u7a0b\u7891
gb.notSpecified = \u672a\u6307\u5b9a
gb.due = \u622a\u6b62\u65e5\u671f
gb.queries = \u67e5\u8be2
gb.searchTicketsTooltip = \u641c\u7d22 {0} \u4e2a\u516c\u9053
gb.searchTickets = \u641c\u7d22\u5de5\u5355
gb.searchTicketsTooltip = \u641c\u7d22 {0} \u4e2a\u4efb\u52a1
gb.searchTickets = \u641c\u7d22\u4efb\u52a1
gb.new = \u65b0\u5efa
gb.newTicket = \u65b0\u5efa\u5de5\u5355
gb.editTicket = \u7f16\u8f91\u5de5\u5355
gb.ticketsWelcome = \u4f60\u53ef\u4ee5\u4f7f\u7528\u5de5\u5355\u7ba1\u7406\u60a8\u7684todo list, \u8ba8\u8bbabugs, \u5408\u4f5c\u5236\u4f5c\u8865\u4e01\u96c6\u3002
gb.createFirstTicket = \u521b\u5efa\u60a8\u7684\u7b2c\u4e00\u4e2a\u5de5\u5355
gb.newTicket = \u65b0\u5efa\u4efb\u52a1
gb.editTicket = \u7f16\u8f91\u4efb\u52a1
gb.ticketsWelcome = \u4f60\u53ef\u4ee5\u4f7f\u7528\u4efb\u52a1\u7ba1\u7406\u60a8\u7684\u5f85\u529e\u4e8b\u9879\uff0c\u8ba8\u8bba bugs\uff0c\u5408\u4f5c\u5236\u4f5c\u8865\u4e01\u96c6\u3002
gb.createFirstTicket = \u521b\u5efa\u60a8\u7684\u7b2c\u4e00\u4e2a\u4efb\u52a1
gb.title = \u6807\u9898

@@ -630,4 +627,4 @@ gb.changedStatus = \u4fee\u6539\u72b6\u6001

gb.proposePatchset = \u63d0\u4ea4\u4e00\u4e2a\u8865\u4e01\u96c6
gb.proposePatchsetNote = \u6b22\u8fce\u60a8\u4e3a\u5f53\u524d\u5de5\u5355\u63d0\u4ea4\u8865\u4e01\u96c6\u3002
gb.proposeInstructions = \u9996\u5148\u521b\u5efa\u4e00\u4e2a\u8865\u4e01\u96c6\uff0c\u7136\u540e\u7528Git\u4e0a\u4f20\u3002 Gitblit \u4f1a\u81ea\u52a8\u901a\u8fc7id\u5c06\u8865\u4e01\u96c6\u4e0e\u5f53\u524dticket\u76f8\u8fde\u63a5\u3002
gb.proposePatchsetNote = \u6b22\u8fce\u4e3a\u5f53\u524d\u4efb\u52a1\u63d0\u4ea4\u8865\u4e01\u96c6\u3002
gb.proposeInstructions = \u9996\u5148\u521b\u5efa\u4e00\u4e2a\u8865\u4e01\u96c6\uff0c\u7136\u540e\u7528 Git \u4e0a\u4f20\u3002Gitblit \u4f1a\u81ea\u52a8\u901a\u8fc7 ID \u5c06\u8865\u4e01\u96c6\u4e0e\u5f53\u524d\u7684\u4efb\u52a1\u76f8\u5173\u8054\u3002
gb.proposeWith = \u5bf9 {0} \u63d0\u4ea4\u4e00\u4e2a\u8865\u4e01\u96c6

@@ -639,11 +636,11 @@ gb.revisionHistory = \u4fee\u8ba2\u5386\u53f2

gb.all = \u6240\u6709
gb.mergeBase = \u5408\u5e76\u57fa\u7840
gb.checkout = \u68c0\u51fa
gb.checkoutViaCommandLine = \u901a\u8fc7\u547d\u4ee4\u884c\u68c0\u51fa
gb.checkoutViaCommandLineNote = \u60a8\u53ef\u4ee5\u68c0\u51fa\u7136\u540e\u5728\u672c\u5730\u4f7f\u7528\u514b\u9686\u6d4b\u8bd5\u4fee\u6539\u7684\u5185\u5bb9\u3002
gb.checkoutStep1 = \u83b7\u53d6\u5f53\u524d\u8865\u4e01\u96c6 \u2014 \u7136\u540e\u5728\u60a8\u7684\u672c\u5730\u9879\u76ee\u76ee\u5f55\u8fd0\u884c
gb.checkoutStep2 = \u5c06\u8865\u4e01\u96c6\u68c0\u51fa\u81f3\u65b0\u7684\u5206\u652f\u4ee5\u8fdb\u884c\u4fee\u8ba2
gb.mergeBase = \u5408\u5e76 base
gb.checkout = \u68c0\u51fa (checkout)
gb.checkoutViaCommandLine = \u901a\u8fc7\u547d\u4ee4\u884c\u68c0\u51fa (checkout)
gb.checkoutViaCommandLineNote = \u60a8\u53ef\u4ee5\u68c0\u51fa (checkout) \u7136\u540e\u5728\u672c\u5730\u4f7f\u7528\u514b\u9686\u7684\u7248\u672c\u5e93\u6d4b\u8bd5\u4fee\u6539\u7684\u5185\u5bb9\u3002
gb.checkoutStep1 = \u83b7\u53d6\u5f53\u524d\u8865\u4e01\u96c6 \u2014 \u7136\u540e\u5728\u60a8\u7684\u672c\u5730\u9879\u76ee\u4e2d\u8fd0\u884c
gb.checkoutStep2 = \u5c06\u8865\u4e01\u96c6\u68c0\u51fa (checkout) \u81f3\u65b0\u7684\u5206\u652f\u4ee5\u8fdb\u884c\u4fee\u8ba2
gb.mergingViaCommandLine = \u4f7f\u7528\u547d\u4ee4\u884c\u5408\u5e76
gb.mergingViaCommandLineNote = \u5982\u679c\u60a8\u4e0d\u60f3\u4f7f\u7528\u5408\u5e76\u6309\u94ae\uff0c\u6216\u8005\u65e0\u6cd5\u81ea\u52a8\u5408\u5e76\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528\u547d\u4ee4\u884c\u624b\u52a8\u5408\u5e76
gb.mergeStep1 = \u68c0\u51fa\u4e00\u4e2a\u65b0\u7684\u5206\u652f\u4ee5\u4fee\u8ba2\u6539\u52a8 \u2014 \u7136\u540e\u5728\u60a8\u7684\u672c\u5730\u9879\u76ee\u76ee\u5f55\u8fd0\u884c
gb.mergeStep1 = \u68c0\u51fa (checkout) \u4e00\u4e2a\u65b0\u7684\u5206\u652f\u4ee5\u4fee\u8ba2\u6539\u52a8 \u2014 \u7136\u540e\u5728\u60a8\u7684\u672c\u5730\u9879\u76ee\u4e2d\u8fd0\u884c
gb.mergeStep2 = \u5f15\u5165\u5df2\u63d0\u4ea4\u4fee\u6539\u540e\u4fee\u8ba2

@@ -655,6 +652,6 @@ gb.mergeStep3 = \u5408\u5e76\u5df2\u63d0\u4ea4\u7684\u4fee\u6539\u7136\u540e\u66f4\u65b0\u670d\u52a1\u5668

gb.ptMerge = \u83b7\u53d6\u548c\u68c0\u51fa\u5f53\u524d\u8865\u4e01\u96c6\u5230\u60a8\u7684\u672c\u5730\u5206\u652f
gb.ptDescription1 = Barnum \u662f\u4e00\u4e2aGit\u7684\u547d\u4ee4\u884c\u5de5\u5177\uff0c\u5b83\u53ef\u4ee5\u7b80\u5316\u4e0eGitblit\u5de5\u5355\u548c\u8865\u4e01\u96c6\u534f\u4f5c\u7684\u6b65\u9aa4\u3002
gb.ptDescription1 = Barnum \u662f\u4e00\u4e2a Git \u7684\u547d\u4ee4\u884c\u5de5\u5177\uff0c\u5b83\u53ef\u4ee5\u7b80\u5316\u4e0e Gitblit \u4efb\u52a1\u548c\u8865\u4e01\u96c6\u534f\u4f5c\u7684\u6b65\u9aa4\u3002
gb.ptSimplifiedCollaboration = \u7b80\u5316\u534f\u4f5c\u683c\u5f0f
gb.ptSimplifiedMerge = \u7b80\u5316\u5408\u5e76\u683c\u5f0f
gb.ptDescription2 = Barnum \u9700\u8981 Python 3 \u4ee5\u53ca\u672c\u5730\u5b89\u88c5Git. \u5b83\u53ef\u4ee5\u5de5\u4f5c\u5728 Windows, Linux, \u4ee5\u53ca Mac OS X\u4e0a\u9762\u3002
gb.ptDescription2 = Barnum \u9700\u8981 Python 3 \u4ee5\u53ca\u672c\u5730\u5b89\u88c5 Git\u3002\u5b83\u53ef\u4ee5\u8fd0\u884c\u5728 Windows, Linux, \u4ee5\u53ca macOS \u4e0a\u3002
gb.stepN = \u7b2c {0} \u6b65

@@ -666,3 +663,3 @@ gb.watchers = \u5173\u6ce8\u8005

gb.removeVote = \u5220\u9664\u6295\u7968
gb.stopWatching = \u505c\u6b62\u5173\u6ce8
gb.stopWatching = \u53d6\u6d88\u5173\u6ce8
gb.watching = \u6b63\u5728\u5173\u6ce8

@@ -685,9 +682,9 @@ gb.comments = \u8bc4\u8bba

gb.approve = \u540c\u610f
gb.hasNotReviewed = \u672a\u88ab\u5ba1\u67e5\u8fc7
gb.hasNotReviewed = \u672a\u7ecf\u5ba1\u67e5
gb.about = \u5173\u4e8e
gb.ticketN = \u5de5\u5355 #{0}
gb.disableUser = \u7981\u6b62\u7528\u6237
gb.disableUserDescription = \u7981\u6b62\u5f53\u524d\u8d26\u6237\u8fdb\u884c\u8ba4\u8bc1
gb.ticketN = \u4efb\u52a1 #{0}
gb.disableUser = \u505c\u7528\u8d26\u6237
gb.disableUserDescription = \u8be5\u8d26\u6237\u5df2\u7ecf\u505c\u7528
gb.any = \u4efb\u610f
gb.milestoneProgress = {0} \u5f00\u542f, {1} \u5173\u95ed
gb.milestoneProgress = {0} \u5f00\u542f\uff0c{1} \u5173\u95ed
gb.nOpenTickets = {0} \u5f00\u542f

@@ -697,39 +694,39 @@ gb.nClosedTickets = {0} \u5173\u95ed

gb.body = \u5185\u5bb9
gb.mergeSha = \u5408\u5e76SHA
gb.mergeSha = \u5408\u5e76 SHA
gb.mergeTo = \u5408\u5e76\u5230
gb.labels = \u6807\u7b7e
gb.reviewers = \u4fee\u8ba2\u4eba
gb.voters = \u6295\u7968\u4eba
gb.reviewers = \u4fee\u8ba2\u8005
gb.voters = \u6295\u7968\u8005
gb.mentions = \u63d0\u53ca
gb.canNotProposePatchset = \u65e0\u6cd5\u63d0\u4ea4\u8865\u4e01\u96c6
gb.repositoryIsMirror = \u5f53\u524d\u7248\u672c\u5e93\u662f\u53ea\u8bfb\u955c\u50cf\u3002
gb.repositoryIsFrozen = \u5f53\u524d\u7248\u672c\u5e93\u5df2\u88ab\u51bb\u7ed3\u3002
gb.repositoryDoesNotAcceptPatchsets = \u5f53\u524d\u7248\u672c\u5e93\u4e0d\u5141\u8bb8\u8865\u4e01\u96c6\u3002
gb.serverDoesNotAcceptPatchsets = \u5f53\u524d\u670d\u52a1\u5668\u4e0d\u5141\u8bb8\u8865\u4e01\u96c6\u3002
gb.ticketIsClosed = \u5f53\u524d\u5de5\u5355\u5df2\u5173\u95ed\u3002
gb.mergeToDescription = \u5408\u5e76\u5de5\u5355\u8865\u4e01\u96c6\u7684\u9ed8\u8ba4\u96c6\u6210\u5206\u652f
gb.anonymousCanNotPropose = \u7981\u6b62\u533f\u540d\u7528\u6237\u63d0\u4ea4\u8865\u4e01\u96c6\u3002
gb.youDoNotHaveClonePermission = \u60a8\u6ca1\u6709\u6743\u9650\u514b\u9686\u5f53\u524d\u7248\u672c\u5e93\u3002
gb.myTickets = \u6211\u7684\u5de5\u5355
gb.yourAssignedTickets = \u8d23\u4efb\u5de5\u5355
gb.newMilestone = \u65b0\u5efa milestone
gb.editMilestone = \u7f16\u8f91 milestone
gb.deleteMilestone = \u5220\u9664 milestone \\"{0}\\"?
gb.milestoneDeleteFailed = \u5220\u9664 milestone ''{0}'' \u5931\u8d25!
gb.notifyChangedOpenTickets = \u5bf9\u53d1\u751f\u53d8\u52a8\u7684\u5df2\u5f00\u542f\u5de5\u5355\u53d1\u9001\u901a\u77e5
gb.repositoryIsMirror = \u5f53\u524d\u7248\u672c\u5e93\u662f\u53ea\u8bfb\u955c\u50cf
gb.repositoryIsFrozen = \u5f53\u524d\u7248\u672c\u5e93\u5df2\u88ab\u51bb\u7ed3
gb.repositoryDoesNotAcceptPatchsets = \u5f53\u524d\u7248\u672c\u5e93\u4e0d\u63a5\u53d7\u8865\u4e01\u96c6
gb.serverDoesNotAcceptPatchsets = \u5f53\u524d\u670d\u52a1\u5668\u4e0d\u63a5\u53d7\u8865\u4e01\u96c6
gb.ticketIsClosed = \u5f53\u524d\u4efb\u52a1\u5df2\u5173\u95ed
gb.mergeToDescription = \u7528\u4e8e\u5408\u5e76\u4efb\u52a1\u4e2d\u7684\u8865\u4e01\u96c6\u7684\u9ed8\u8ba4\u96c6\u6210\u5206\u652f
gb.anonymousCanNotPropose = \u7981\u6b62\u533f\u540d\u7528\u6237\u63d0\u4ea4\u8865\u4e01\u96c6
gb.youDoNotHaveClonePermission = \u60a8\u6ca1\u6709\u6743\u9650\u514b\u9686\u5f53\u524d\u7248\u672c\u5e93
gb.myTickets = \u6211\u7684\u4efb\u52a1
gb.yourAssignedTickets = \u6307\u5b9a\u7ed9\u6211\u7684\u4efb\u52a1
gb.newMilestone = \u521b\u5efa\u91cc\u7a0b\u7891
gb.editMilestone = \u7f16\u8f91\u91cc\u7a0b\u7891
gb.deleteMilestone = \u5220\u9664\u91cc\u7a0b\u7891 \"{0}\"?
gb.milestoneDeleteFailed = \u65e0\u6cd5\u5220\u9664\u91cc\u7a0b\u7891 ''{0}''
gb.notifyChangedOpenTickets = \u5df2\u5f00\u542f\u4efb\u52a1\u53d8\u52a8\u901a\u77e5
gb.overdue = \u8fc7\u671f
gb.openMilestones = \u5df2\u5f00\u542f milestones
gb.closedMilestones = \u5df2\u5173\u95ed milestones
gb.openMilestones = \u5df2\u5f00\u542f\u7684\u91cc\u7a0b\u7891
gb.closedMilestones = \u5df2\u5173\u95ed\u7684\u91cc\u7a0b\u7891
gb.administration = \u7ba1\u7406
gb.plugins = \u63d2\u4ef6
gb.extensions = \u6269\u5c55
gb.pleaseSelectProject = \u8bf7\u9009\u62e9\u9879\u76ee!
gb.pleaseSelectProject = \u8bf7\u9009\u62e9\u9879\u76ee
gb.accessPolicy = \u8bbf\u95ee\u7b56\u7565
gb.accessPolicyDescription = \u8bf7\u9009\u62e9\u4e00\u4e2a\u63a7\u5236\u7248\u672c\u5e93\u53ef\u89c1\u6027\u4ee5\u53caGit\u8bbf\u95ee\u6743\u9650\u7684\u8bbf\u95ee\u7b56\u7565\u3002
gb.accessPolicyDescription = \u8bf7\u9009\u62e9\u4e00\u4e2a\u63a7\u5236\u7248\u672c\u5e93\u53ef\u89c1\u6027\u4ee5\u53ca Git \u8bbf\u95ee\u6743\u9650\u7684\u8bbf\u95ee\u7b56\u7565
gb.anonymousPolicy = \u533f\u540d\u67e5\u770b, \u514b\u9686\u548c\u63a8\u9001
gb.anonymousPolicyDescription = \u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u67e5\u770b\uff0c\u514b\u9686\u4ee5\u53ca\u63a8\u9001\u81f3\u6b64\u7248\u672c\u5e93\u3002
gb.authenticatedPushPolicy = \u9650\u5236\u63a8\u9001 (\u6388\u6743\u8bbf\u95ee)
gb.authenticatedPushPolicyDescription = \u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u67e5\u770b\u4ee5\u53ca\u514b\u9686\u6b64\u7248\u672c\u5e93\u3002\u4efb\u4f55\u5df2\u6388\u6743\u7528\u6237\u62e5\u6709RW+\u63a8\u9001\u6743\u9650\u3002
gb.namedPushPolicy = \u9650\u5236\u63a8\u9001 (\u6307\u5b9a\u7528\u6237)
gb.namedPushPolicyDescription = \u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u67e5\u770b\u4ee5\u53ca\u514b\u9686\u6b64\u7248\u672c\u5e93\u3002 \u60a8\u53ef\u4ee5\u9009\u62e9\u62e5\u6709\u63a8\u9001\u6743\u9650\u7684\u7528\u6237\u3002
gb.anonymousPolicyDescription = \u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u67e5\u770b\uff0c\u514b\u9686\u4ee5\u53ca\u63a8\u9001\u81f3\u6b64\u7248\u672c\u5e93
gb.authenticatedPushPolicy = \u9650\u5236\u63a8\u9001\uff08\u6388\u6743\u8bbf\u95ee\uff09
gb.authenticatedPushPolicyDescription = \u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u67e5\u770b\u4ee5\u53ca\u514b\u9686\u6b64\u7248\u672c\u5e93\u3002\u5df2\u6388\u6743\u7528\u6237\u62e5\u6709\u8bfb\u53d6\u3001\u5199\u5165\u548c\u63a8\u9001\u6743\u9650\u3002
gb.namedPushPolicy = \u9650\u5236\u63a8\u9001\uff08\u6307\u5b9a\u7528\u6237\uff09
gb.namedPushPolicyDescription = \u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u67e5\u770b\u4ee5\u53ca\u514b\u9686\u6b64\u7248\u672c\u5e93\u3002\u60a8\u53ef\u4ee5\u9009\u62e9\u62e5\u6709\u63a8\u9001\u6743\u9650\u7684\u7528\u6237\u3002
gb.clonePolicy = \u9650\u5236\u514b\u9686\uff0c\u63a8\u9001

@@ -744,22 +741,22 @@ gb.clonePolicyDescription = \u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u770b\u5230\u6b64\u7248\u672c\u5e93\u3002\u60a8\u53ef\u4ee5\u9009\u62e9\u62e5\u6709\u514b\u9686\u548c\u63a8\u9001\u6743\u9650\u7684\u7528\u6237\u3002

gb.initWithGitignore = \u52a0\u5165 .gitignore \u6587\u4ef6
gb.initWithGitignoreDescription = \u6b64\u529f\u80fd\u4f1a\u751f\u6210\u4e00\u4e2a\u914d\u7f6e\u6587\u4ef6\uff0c\u65e8\u5728\u63d0\u793a Git \u5ba2\u6237\u7aef\u5ffd\u7565\u5bf9\u5e94\u7684\u6587\u4ef6\u6216\u6587\u4ef6\u5939\u3002
gb.initWithGitignoreDescription = \u6b64\u529f\u80fd\u4f1a\u751f\u6210\u4e00\u4e2a\u914d\u7f6e\u6587\u4ef6\uff0c\u7528\u4e8e\u63d0\u793a Git \u5ba2\u6237\u7aef\u5ffd\u7565\u5bf9\u5e94\u7684\u6587\u4ef6\u6216\u6587\u4ef6\u5939\u3002
gb.pleaseSelectGitIgnore = \u8bf7\u9009\u62e9\u4e00\u4e2a .gitignore \u6587\u4ef6
gb.receive = receive
gb.permissions = permissions
gb.ownersDescription = \u7248\u672c\u5e93\u62e5\u6709\u8005\u62e5\u6709\u7248\u672c\u5e93\u7684\u6240\u6709\u7ba1\u7406\u6743\u9650\uff0c\u4f46\u662f\u53ea\u5141\u8bb8\u4fee\u6539\u79c1\u6709\u7248\u672c\u5e93\u7684\u540d\u79f0\u3002
gb.userPermissionsDescription = \u60a8\u53ef\u4ee5\u8bbe\u7f6e\u79c1\u6709\u7528\u6237\u6743\u9650\u3002 \u6b64\u8bbe\u7f6e\u4f1a\u8986\u76d6\u56e2\u961f\u6743\u9650\u4ee5\u53caregex\u6743\u9650\u3002
gb.teamPermissionsDescription = \u60a8\u53ef\u4ee5\u8bbe\u7f6e\u79c1\u6709\u56e2\u961f\u6743\u9650\u3002 \u6b64\u8bbe\u7f6e\u4f1a\u8986\u76d6regex\u6743\u9650\u3002
gb.ticketSettings = \u5de5\u5355\u8bbe\u7f6e
gb.receiveSettings = Receive \u8bbe\u7f6e
gb.receiveSettingsDescription = Receive\u8bbe\u7f6e\u8bbe\u5b9a\u63a8\u9001\u81f3\u7248\u672c\u5e93\u65f6\u7684\u884c\u4e3a\u3002
gb.preReceiveDescription = Pre-receive hooks \u4f1a\u5728\u63a8\u9001\u63a5\u6536\u540e\uff0c refs \u66f4\u65b0<em>\u4e4b\u524d</em>\u6267\u884c\u3002<p>\u8fd9\u79cdhook\u662f\u8fdb\u884c\u63a8\u9001\u62d2\u7edd\u7684\u597d\u5de5\u5177\u3002</p>
gb.postReceiveDescription = Post-receive hooks \u4f1a\u5728\u63a8\u9001\u63a5\u6536\u540e\uff0c refs \u66f4\u65b0<em>\u4e4b\u540e</em>\u6267\u884c\u3002<p>\u8fd9\u79cdhook\u662f\u8fdb\u884c\u901a\u77e5\uff0c\u4f7f\u7528\u6784\u5efa\u89e6\u53d1\u5668\u7b49\u7684\u597d\u5de5\u5177\u3002</p>
gb.federationStrategyDescription = \u8bbe\u7f6e\u662f\u5426\u4ee5\u53ca\u5982\u4f55\u5c06\u5f53\u524d\u7248\u672c\u5e93\u4e0e\u5176\u4ed6Gitblit\u8fdb\u884cfederate\u3002
gb.federationSetsDescription = \u5f53\u524d\u7248\u672c\u5e93\u5c06\u4f1a\u88ab\u5305\u542b\u8fdb\u9009\u5b9a\u7684federation\u96c6\u4e2d\u3002
gb.miscellaneous = miscellaneous
gb.receive = \u63a5\u6536
gb.permissions = \u6743\u9650
gb.ownersDescription = \u7248\u672c\u5e93\u6240\u6709\u8005\u62e5\u6709\u7248\u672c\u5e93\u7684\u6240\u6709\u7ba1\u7406\u6743\u9650\uff0c\u4f46\u662f\u53ea\u5141\u8bb8\u4fee\u6539\u79c1\u6709\u7248\u672c\u5e93\u7684\u540d\u79f0\u3002
gb.userPermissionsDescription = \u60a8\u53ef\u4ee5\u8bbe\u7f6e\u5355\u4e2a\u7528\u6237\u6743\u9650\u3002\u6b64\u8bbe\u7f6e\u4f1a\u8986\u76d6\u56e2\u961f\u6743\u9650\u4ee5\u53ca\u6b63\u5219\u8868\u8fbe\u5f0f\u8bbe\u7f6e\u7684\u6743\u9650\u3002
gb.teamPermissionsDescription = \u60a8\u53ef\u4ee5\u8bbe\u7f6e\u5355\u4e2a\u56e2\u961f\u6743\u9650\u3002\u6b64\u8bbe\u7f6e\u4f1a\u8986\u76d6\u6b63\u5219\u8868\u8fbe\u5f0f\u8bbe\u7f6e\u7684\u6743\u9650\u3002
gb.ticketSettings = \u4efb\u52a1\u8bbe\u7f6e
gb.receiveSettings = \u63a5\u6536\u65b9\u5f0f\u8bbe\u7f6e
gb.receiveSettingsDescription = \u8bbe\u7f6e\u63a8\u9001\u81f3\u7248\u672c\u5e93\u65f6\u7684\u63a5\u6536\u65b9\u5f0f\u3002
gb.preReceiveDescription = Pre-receive hooks \u4f1a\u5728\u63a8\u9001\u63a5\u6536\u540e\uff0crefs \u66f4\u65b0<em>\u4e4b\u524d</em>\u6267\u884c\u3002<p>\u8fd9\u79cd hook \u662f\u8fdb\u884c\u63a8\u9001\u62d2\u7edd\u7684\u597d\u5de5\u5177\u3002</p>
gb.postReceiveDescription = Post-receive hooks \u4f1a\u5728\u63a8\u9001\u63a5\u6536\u540e\uff0crefs \u66f4\u65b0<em>\u4e4b\u540e</em>\u6267\u884c\u3002<p>\u8fd9\u79cd hook \u662f\u8fdb\u884c\u901a\u77e5\uff0c\u4f7f\u7528\u6784\u5efa\u89e6\u53d1\u5668\u7b49\u7684\u597d\u5de5\u5177\u3002</p>
gb.federationStrategyDescription = \u8bbe\u7f6e\u662f\u5426\u4ee5\u53ca\u5982\u4f55\u5c06\u5f53\u524d\u7248\u672c\u5e93\u4e0e\u5176\u4ed6 Gitblit \u8fdb\u884c federate\u3002
gb.federationSetsDescription = \u5f53\u524d\u7248\u672c\u5e93\u5c06\u4f1a\u88ab\u5305\u542b\u8fdb\u9009\u5b9a\u7684 federation \u96c6\u4e2d\u3002
gb.miscellaneous = \u5176\u4ed6
gb.originDescription = \u5f53\u524d\u7248\u672c\u5e93\u7684\u514b\u9686\u6e90\u5730\u5740\u3002
gb.gc = GC
gb.garbageCollection = \u5783\u573e\u6536\u96c6
gb.garbageCollectionDescription = \u5783\u573e\u6536\u96c6\u5668\u4f1a\u5c06\u5ba2\u6237\u7aef\u6240\u53d1\u9001\u7684\u677e\u6563\u6587\u4ef6\u6253\u5305\u5e76\u5220\u9664\u5f53\u524d\u7248\u672c\u5e93\u4e2d\u672a\u88ab\u5f15\u7528\u7684\u5bf9\u8c61\u3002
gb.commitMessageRendererDescription = \u53ef\u4ee5\u5c06\u63d0\u4ea4\u4fe1\u606f\u663e\u793a\u4e3a\u7eaf\u6587\u672c\u6216\u8005\u5df2\u6392\u7248\u7684Markup\u6587\u672c
gb.gc = \u5783\u573e\u56de\u6536 (GC)
gb.garbageCollection = \u5783\u573e\u56de\u6536
gb.garbageCollectionDescription = \u5783\u573e\u6536\u96c6\u5668\u4f1a\u5c06\u5ba2\u6237\u7aef\u6240\u63a8\u9001\u7684\u677e\u6563\u6587\u4ef6\u6253\u5305\u5e76\u5220\u9664\u5f53\u524d\u7248\u672c\u5e93\u4e2d\u672a\u88ab\u5f15\u7528\u7684\u5bf9\u8c61\u3002
gb.commitMessageRendererDescription = \u53ef\u4ee5\u5c06\u63d0\u4ea4\u4fe1\u606f\u663e\u793a\u4e3a\u7eaf\u6587\u672c\u6216\u8005\u5df2\u6392\u7248\u7684 Markup \u6587\u672c
gb.preferences = \u504f\u597d

@@ -769,16 +766,61 @@ gb.accountPreferences = \u7528\u6237\u504f\u597d

gb.languagePreference = \u8bed\u8a00\u504f\u597d
gb.languagePreferenceDescription = \u9009\u62e9\u60a8\u559c\u6b22\u7684Gitblit\u7ffb\u8bd1
gb.emailMeOnMyTicketChanges = \u5728\u6211\u7684\u5de5\u5355\u53d1\u751f\u53d8\u5316\u540e\u90ae\u4ef6\u901a\u77e5\u6211
gb.emailMeOnMyTicketChangesDescription = \u5bf9\u6211\u5728\u5de5\u5355\u4e2d\u4f5c\u51fa\u7684\u4fee\u6539\u53d1\u9001\u90ae\u4ef6\u901a\u77e5\u3002
gb.displayNameDescription = \u9009\u62e9\u663e\u793a\u540d\u79f0
gb.emailAddressDescription = \u63a5\u6536\u901a\u77e5\u7684\u4e3b\u8981\u90ae\u7bb1\u5730\u5740
gb.sshKeys = SSH Keys
gb.sshKeysDescription = SSH \u516c\u7ea6\u8ba4\u8bc1\u662f\u4e00\u79cd\u4e0d\u540c\u4e8e\u5bc6\u7801\u8ba4\u8bc1\u7684\u5b89\u5168\u8ba4\u8bc1\u65b9\u6cd5\u3002
gb.addSshKey = \u6dfb\u52a0 SSH Key
gb.key = Key
gb.comment = \u53d1\u8868
gb.sshKeyCommentDescription = \u8f93\u5165\u8bc4\u8bba\uff08\u53ef\u4e3a\u7a7a\uff09. \u5982\u679c\u4e3a\u7a7a\uff0c \u8bc4\u8bba\u5185\u5bb9\u5c06\u4f1a\u4ece\u4e3b\u8981\u6570\u636e\u4e2d\u63d0\u53d6\u3002
gb.languagePreferenceDescription = \u9009\u62e9\u60a8\u7684\u8bed\u8a00
gb.emailMeOnMyTicketChanges = \u5728\u6211\u7684\u4efb\u52a1\u53d1\u751f\u53d8\u66f4\u540e\u90ae\u4ef6\u901a\u77e5\u6211
gb.emailMeOnMyTicketChangesDescription = \u5bf9\u6211\u5728\u4efb\u52a1\u4e2d\u4f5c\u51fa\u7684\u4fee\u6539\u53d1\u9001\u90ae\u4ef6\u901a\u77e5
gb.displayNameDescription = \u8bbe\u7f6e\u663e\u793a\u540d\u79f0
gb.emailAddressDescription = \u7528\u4e8e\u63a5\u6536\u901a\u77e5\u7684\u4e3b\u8981\u7535\u5b50\u90ae\u4ef6\u5730\u5740
gb.sshKeys = SSH \u5bc6\u94a5
gb.sshKeysDescription = SSH \u5bc6\u94a5\u8ba4\u8bc1\u662f\u4e00\u79cd\u4e0d\u540c\u4e8e\u5bc6\u7801\u8ba4\u8bc1\u7684\u5b89\u5168\u8ba4\u8bc1\u65b9\u6cd5\u3002
gb.addSshKey = \u6dfb\u52a0 SSH \u5bc6\u94a5
gb.key = \u5bc6\u94a5
gb.sshKeyCommentDescription = \u8f93\u5165\u8bc4\u8bba\uff08\u53ef\u4e3a\u7a7a\uff09\u3002\u5982\u679c\u4e3a\u7a7a\uff0c\u8bc4\u8bba\u5185\u5bb9\u5c06\u4f1a\u4ece\u4e3b\u8981\u6570\u636e\u4e2d\u63d0\u53d6\u3002
gb.permission = \u6743\u9650
gb.sshKeyPermissionDescription = \u8bbe\u7f6eSSH key\u7684\u8bbf\u95ee\u6743\u9650
gb.transportPreference = Transport \u504f\u597d
gb.transportPreferenceDescription = \u9009\u62e9\u60a8\u7528\u6765\u514b\u9686\u7684 Transport
gb.sshKeyPermissionDescription = \u8bbe\u7f6e SSH \u5bc6\u94a5\u7684\u8bbf\u95ee\u6743\u9650
gb.transportPreference = \u4f20\u8f93\u504f\u597d
gb.transportPreferenceDescription = \u9009\u62e9\u60a8\u7528\u6765\u514b\u9686\u7684\u4f20\u8f93\u65b9\u5f0f
gb.ticketStatus = \u72b6\u6001
gb.maintenanceTickets = \u7ef4\u62a4
gb.mergeType = \u5408\u5e76\u7c7b\u578b
gb.mergeTypeDescription = \u4ec5\u5728\u5fc5\u8981\u65f6\u5feb\u901f\u5408\u5e76\u4efb\u52a1\uff0c\u6216\u8005\u603b\u662f\u4e0e\u5408\u5e76\u63d0\u4ea4\u5230\u96c6\u6210\u5206\u652f
gb.priority = \u4f18\u5148\u7ea7
gb.severity = \u91cd\u8981\u6027
gb.sortHighestPriority = \u6700\u9ad8\u4f18\u5148\u7ea7
gb.sortLowestPriority = \u6700\u4f4e\u4f18\u5148\u7ea7
gb.sortHighestSeverity = \u6700\u91cd\u8981
gb.sortLowestSeverity = \u6700\u4e0d\u91cd\u8981
gb.missingIntegrationBranchMore = \u76ee\u6807\u5206\u652f\u4e0d\u5728\u6b64\u7248\u672c\u5e93\u4e2d
gb.diffDeletedFileSkipped = \uff08\u5df2\u5220\u9664\uff09
gb.diffFileDiffTooLarge = \u6587\u4ef6\u592a\u5927
gb.diffNewFile = \u5bf9\u6bd4\u65b0\u6587\u4ef6
gb.diffDeletedFile = \u6587\u4ef6\u5df2\u5220\u9664
gb.diffRenamedFile = \u6587\u4ef6\u540d\u4ece {0} \u4fee\u6539
gb.diffCopiedFile = \u6587\u4ef6\u4ece {0} \u590d\u5236
gb.diffTruncated = \u5728\u4e0a\u8ff0\u6587\u4ef6\u622a\u65ad\u540e\u5bf9\u6bd4
gb.opacityAdjust = \u8c03\u6574\u900f\u660e\u5ea6
gb.blinkComparator = \u7728\u773c\u6bd4\u8f83\u5668
gb.imgdiffSubtract = \u76f8\u51cf\uff08\u9ed1\u8272\u4e3a\u76f8\u540c\uff09
gb.deleteRepositoryHeader = \u5220\u9664\u7248\u672c\u5e93
gb.deleteRepositoryDescription = \u5220\u9664\u7248\u672c\u5e93\u5c06\u4e0d\u53ef\u64a4\u9500\u3002
gb.show_whitespace = \u663e\u793a\u7a7a\u767d
gb.ignore_whitespace = \u5ffd\u7565\u7a7a\u767d
gb.allRepositories = \u6240\u6709\u7248\u672c\u5e93
gb.oid = \u5bf9\u8c61 ID
gb.filestore = \u6587\u4ef6\u5b58\u50a8
gb.filestoreStats = \u5df2\u5b58\u50a8 {0} \u4e2a\u6587\u4ef6\uff0c\u5360\u7528\u7a7a\u95f4 {1}\u3002 (\u53ef\u7528\u7a7a\u95f4 {2})
gb.statusChangedOn = \u4fee\u6539\u65e5\u671f
gb.statusChangedBy = \u4fee\u6539\u8005
gb.filestoreHelp = \u8fdb\u4e00\u6b65\u4e86\u89e3\u6587\u4ef6\u5b58\u50a8\u529f\u80fd
gb.editFile = \u7f16\u8f91\u6587\u4ef6
gb.continueEditing = \u7ee7\u7eed\u7f16\u8f91
gb.commitChanges = \u63d0\u4ea4\u66f4\u6539
gb.fileNotMergeable = \u65e0\u6cd5\u63d0\u4ea4\u66f4\u6539 {0}\u3002\u6b64\u6587\u4ef6\u65e0\u6cd5\u81ea\u52a8\u5408\u5e76\u3002
gb.fileCommitted = \u6210\u529f\u63d0\u4ea4\u66f4\u6539 {0}\u3002
gb.deletePatchset = \u5220\u9664\u8865\u4e01\u96c6 {0}
gb.deletePatchsetSuccess = \u5df2\u5220\u9664\u8865\u4e01\u96c6 {0}\u3002
gb.deletePatchsetFailure = \u5220\u9664\u8865\u4e01\u96c6 {0} \u65f6\u53d1\u751f\u9519\u8bef\u3002
gb.referencedByCommit = \u88ab\u63d0\u4ea4\u5f15\u7528\u3002
gb.referencedByTicket = \u88ab\u4efb\u52a1\u5f15\u7528\u3002
gb.emailClientCertificateSubject = \u7528\u4e8e {0} \u7684 Gitblit \u5ba2\u6237\u7aef\u8bc1\u4e66
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = \u6c49\u5b57

@@ -785,2 +785,5 @@ #!

gb.referencedByTicket = Referenced by ticket.
gb.emailClientCertificateSubject = \u4F3A\u670D\u5668 {0} \u9023\u7DDA\u6191\u8B49
gb.emailClientCertificateSubject = \u4F3A\u670D\u5668 {0} \u9023\u7DDA\u6191\u8B49
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = \u6f22\u5b57

@@ -173,3 +173,2 @@ gb.repository = repository

gb.since = since
gb.status = status
gb.bootDate = boot date

@@ -362,3 +361,3 @@ gb.servletContainer = servlet container

gb.rewindPermission = {0} (push, ref creation+deletion+rewind)
gb.permission = permission
gb.permission = Permission
gb.regexPermission = this permission is set from regular expression \"{0}\"

@@ -649,3 +648,3 @@ gb.accessDenied = access denied

gb.reviews = reviews
gb.veto = veto
gb.veto = veto
gb.needsImprovement = needs improvement

@@ -729,3 +728,3 @@ gb.looksGood = looks good

gb.originDescription = The url from which this repository was cloned.
gb.gc = GC
gb.gc = GC
gb.garbageCollection = Garbage Collection

@@ -747,5 +746,4 @@ gb.garbageCollectionDescription = The garbage collector will pack loose objects pushed from clients and will remove unreferenced objects from the repository.

gb.key = Key
gb.comment = Comment
gb.sshKeyComment = Comment
gb.sshKeyCommentDescription = Enter an optional comment. If blank, the comment will be extracted from the key data.
gb.permission = Permission
gb.sshKeyPermissionDescription = Specify the access permission for the SSH key

@@ -793,1 +791,4 @@ gb.transportPreference = Transport Preference

gb.emailClientCertificateSubject = Your Gitblit client certificate for {0}
# This last property for unit tests to test successful loading of the resource file
gb.loadLang = default

@@ -22,4 +22,2 @@ /*

import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;

@@ -51,3 +49,5 @@ import java.util.ArrayList;

import org.pegdown.ast.ExpImageNode;
import org.pegdown.ast.ExpLinkNode;
import org.pegdown.ast.RefImageNode;
import org.pegdown.ast.RefLinkNode;
import org.pegdown.ast.WikiLinkNode;

@@ -270,3 +270,3 @@ import org.pegdown.plugins.ToHtmlSerializerPlugin;

String url;
if (imagePath.indexOf("://") == -1) {
if (! isFullUrl(imagePath)) {
// relative image

@@ -287,3 +287,3 @@ String path = doc.getRelativePath(imagePath);

if (hrefOrHashName.charAt(0) != '#') {
if (hrefOrHashName.indexOf("://") == -1) {
if (! isFullUrl(hrefOrHashName)) {
// relative link

@@ -329,3 +329,3 @@ String path = doc.getRelativePath(hrefOrHashName);

public Rendering render(ExpImageNode node, String text) {
if (node.url.indexOf("://") == -1) {
if (! isFullUrl(node.url)) {
// repository-relative image link

@@ -344,3 +344,3 @@ String path = doc.getRelativePath(node.url);

Rendering rendering;
if (url.indexOf("://") == -1) {
if (! isFullUrl(url)) {
// repository-relative image link

@@ -365,2 +365,33 @@ String path = doc.getRelativePath(url);

}
@Override
public Rendering render(ExpLinkNode node, String text) {
// Relative file-like MD links needs to be re-mapped to be relative to
// repository name so that they display correctly sub-folder files
// Absolute links must be left un-touched.
// Note: The absolute lack of comments in ExpLinkNode is... well...
// I assume, that getRelativePath is handling "file like" links
// like "/xx/tt" or "../somefolder".
if (isFullUrl(node.url)) {
// This is URL, fallback to superclass.
return super.render(node,text);
}
// repository-relative link
String path = doc.getRelativePath(node.url);
String url = getWicketUrl(DocPage.class, repositoryName, commitId, path);
return new Rendering(url, text);
}
@Override
public Rendering render(RefLinkNode node, String url, String title, String text) {
if (isFullUrl(url)) {
// This is URL, fallback to superclass.
return super.render(node, url, title, text);
}
// repository-relative link
String path = doc.getRelativePath(url);
String local_url = getWicketUrl(DocPage.class, repositoryName, commitId, path);
return super.render(node, local_url, title, text);
}
};

@@ -374,10 +405,23 @@

private boolean isFullUrl(String url)
{
// Relative file-like links needs to be re-mapped to be relative to
// repository name so that they display correctly sub-folder files
// Absolute links must be left un-touched.
// Check if given string is a full URL link. The easiest is to ask java to parse URL
// and let it fail. Shame java.net.URL has no method to validate URL without
// throwing.
try {
new java.net.URL(url);
// Success, this is a URL
return true;
} catch (java.net.MalformedURLException ignored) {};
// This is a relative link
return false;
}
private String getWicketUrl(Class<? extends Page> pageClass, final String repositoryName, final String commitId, final String document) {
String fsc = settings.getString(Keys.web.forwardSlashCharacter, "/");
String encodedPath = document.replace(' ', '-');
try {
encodedPath = URLEncoder.encode(encodedPath, "UTF-8");
} catch (UnsupportedEncodingException e) {
logger.error(null, e);
}
encodedPath = encodedPath.replace("/", fsc).replace("%2F", fsc);

@@ -384,0 +428,0 @@

@@ -111,3 +111,3 @@ /*

blobPath, repositoryName, objectId);
logger.error(notFound);
logger().error(notFound);
add(new Label("annotation").setVisible(false));

@@ -114,0 +114,0 @@ add(new Label("missingBlob", missingBlob(blobPath, commit)).setEscapeModelStrings(false));

@@ -126,3 +126,3 @@ /*

logger.trace("Commiting Edit File page: " + commitIdAtLoad.getObject());
logger().trace("Commiting Edit File page: " + commitIdAtLoad.getObject());

@@ -129,0 +129,0 @@ DirCache index = DirCache.newInCore();

@@ -97,3 +97,3 @@ /*

} catch (ParseException e) {
logger.error("Unable to parse date: " + metric.name);
logger().error("Unable to parse date: " + metric.name);
return;

@@ -100,0 +100,0 @@ }

@@ -48,3 +48,3 @@ /*

private final Logger logger = LoggerFactory.getLogger(getClass().getSimpleName());
private transient Logger logger;

@@ -99,3 +99,3 @@ String contentType;

objectId, repositoryName);
logger.error(objectNotFound);
logger().error(objectNotFound);
throw new AbortWithWebErrorCodeException(HttpServletResponse.SC_NOT_FOUND, objectNotFound);

@@ -109,3 +109,3 @@ }

} catch (Exception e) {
logger.error("Failed to write binary response", e);
logger().error("Failed to write binary response", e);
}

@@ -118,3 +118,3 @@ } else {

objectId, repositoryName);
logger.error(commitNotFound);
logger().error(commitNotFound);
throw new AbortWithWebErrorCodeException(HttpServletResponse.SC_NOT_FOUND, commitNotFound);

@@ -155,3 +155,3 @@ }

if (image == null) {
logger.error(blobNotFound);
logger().error(blobNotFound);
throw new AbortWithWebErrorCodeException(HttpServletResponse.SC_NOT_FOUND, blobNotFound);

@@ -165,3 +165,3 @@ }

} catch (IOException e) {
logger.error("Failed to write image response", e);
logger().error("Failed to write image response", e);
}

@@ -173,3 +173,3 @@ break;

if (binary == null) {
logger.error(blobNotFound);
logger().error(blobNotFound);
throw new AbortWithWebErrorCodeException(HttpServletResponse.SC_NOT_FOUND, blobNotFound);

@@ -203,3 +203,3 @@ }

} catch (IOException e) {
logger.error("Failed to write binary response", e);
logger().error("Failed to write binary response", e);
}

@@ -212,3 +212,3 @@ break;

if (content == null) {
logger.error(blobNotFound);
logger().error(blobNotFound);
throw new AbortWithWebErrorCodeException(HttpServletResponse.SC_NOT_FOUND, blobNotFound);

@@ -221,3 +221,3 @@ }

} catch (Exception e) {
logger.error("Failed to write text response", e);
logger().error("Failed to write text response", e);
}

@@ -231,3 +231,3 @@ }

if (content == null) {
logger.error(blobNotFound);
logger().error(blobNotFound);
throw new AbortWithWebErrorCodeException(HttpServletResponse.SC_NOT_FOUND, blobNotFound);

@@ -240,3 +240,3 @@ }

} catch (Exception e) {
logger.error("Failed to write text response", e);
logger().error("Failed to write text response", e);
}

@@ -250,2 +250,9 @@ }

protected Logger logger() {
if (logger == null) {
logger = LoggerFactory.getLogger(getClass());
}
return logger;
}
@Override

@@ -252,0 +259,0 @@ protected void setHeaders(WebResponse response) {

@@ -45,4 +45,2 @@ /*

import org.eclipse.jgit.revwalk.RevCommit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@@ -82,4 +80,2 @@ import com.gitblit.Constants;

protected final Logger logger = LoggerFactory.getLogger(getClass());
private final String PARAM_STAR = "star";

@@ -98,3 +94,3 @@

private boolean showAdmin;
private boolean isOwner;
private final boolean isOwner;

@@ -150,3 +146,3 @@ public RepositoryPage(PageParameters params) {

} catch (GitBlitException e) {
logger.error("Failed to update user " + user.username, e);
logger().error("Failed to update user " + user.username, e);
error(getString("gb.failedToUpdateUser"), false);

@@ -586,3 +582,3 @@ }

protected void addRefs(Repository r, RevCommit c) {
add(new RefsPanel("refsPanel", repositoryName, c, JGitUtils.getAllRefs(r, getRepositoryModel().showRemoteBranches)));
add(new RefsPanel("refsPanel", repositoryName, JGitUtils.getAllRefs(r, getRepositoryModel().showRemoteBranches).get(c.getId())));
}

@@ -589,0 +585,0 @@

@@ -193,3 +193,3 @@ /*

} catch (ParseException e) {
logger.error("Unable to parse date: " + metric.name);
logger().error("Unable to parse date: " + metric.name);
return charts;

@@ -196,0 +196,0 @@ }

@@ -183,2 +183,3 @@ /*

new Language("Português", "pt_BR"),
new Language("Русский","ru"),
new Language("簡體中文", "zh_CN"),

@@ -185,0 +186,0 @@ new Language("正體中文", "zh_TW"));

@@ -47,3 +47,5 @@ /*

import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryCommit;
import com.gitblit.models.SubmoduleModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.JGitUtils;

@@ -65,3 +67,3 @@ import com.gitblit.utils.MarkdownUtils;

private boolean hasMore;
private final boolean hasMore;

@@ -106,6 +108,5 @@ public HistoryPanel(String wicketId, final String repositoryName, final String objectId,

// manually locate path in tree
TreeWalk tw = new TreeWalk(r);
tw.reset();
tw.setRecursive(true);
try {
try (TreeWalk tw = new TreeWalk(r)) {
tw.reset();
tw.setRecursive(true);
tw.addTree(commit.getTree());

@@ -121,4 +122,2 @@ tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));

} catch (Exception e) {
} finally {
tw.close();
}

@@ -143,3 +142,3 @@ }

final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs);
Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs);
List<RevCommit> commits;

@@ -160,4 +159,12 @@ if (pageResults) {

final int hashLen = app().settings().getInteger(Keys.web.shortCommitIdLength, 6);
ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
DataView<RevCommit> logView = new DataView<RevCommit>("commit", dp) {
List<RepositoryCommit> repoCommits = new ArrayList<>(commits.size());
for (RevCommit c : commits) {
RepositoryCommit repoCommit = new RepositoryCommit(repositoryName, "", c);
if (allRefs.containsKey(c)) {
repoCommit.setRefs(allRefs.get(c));
}
repoCommits.add(repoCommit);
}
ListDataProvider<RepositoryCommit> dp = new ListDataProvider<RepositoryCommit>(repoCommits);
DataView<RepositoryCommit> logView = new DataView<RepositoryCommit>("commit", dp) {
private static final long serialVersionUID = 1L;

@@ -167,5 +174,5 @@ int counter;

@Override
public void populateItem(final Item<RevCommit> item) {
final RevCommit entry = item.getModelObject();
final Date date = JGitUtils.getAuthorDate(entry);
public void populateItem(final Item<RepositoryCommit> item) {
final RepositoryCommit entry = item.getModelObject();
Date date = entry.getAuthorIdent().getWhen();

@@ -192,3 +199,3 @@ item.add(WicketUtils.createDateLabel("commitDate", date, getTimeZone(), getTimeUtils()));

String trimmedMessage = shortMessage;
if (allRefs.containsKey(entry.getId())) {
if (!ArrayUtils.isEmpty(entry.getRefs())) {
trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG_REFS);

@@ -206,3 +213,3 @@ } else {

item.add(new RefsPanel("commitRefs", repositoryName, entry, allRefs));
item.add(new RefsPanel("commitRefs", repositoryName, entry.getRefs()));

@@ -226,3 +233,3 @@ if (isTree) {

Repository repository = app().repositories().getRepository(repositoryName);
String submoduleId = JGitUtils.getSubmoduleCommitId(repository, path, entry);
String submoduleId = JGitUtils.getSubmoduleCommitId(repository, path, entry.getCommit());
repository.close();

@@ -229,0 +236,0 @@ if (StringUtils.isEmpty(submoduleId)) {

@@ -18,2 +18,3 @@ /*

import java.util.ArrayList;
import java.util.Date;

@@ -39,3 +40,5 @@ import java.util.List;

import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryCommit;
import com.gitblit.servlet.BranchGraphServlet;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.JGitUtils;

@@ -55,3 +58,3 @@ import com.gitblit.utils.StringUtils;

private boolean hasMore;
private final boolean hasMore;

@@ -67,3 +70,3 @@ public LogPanel(String wicketId, final String repositoryName, final String objectId,

final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs);
Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs);
List<RevCommit> commits;

@@ -82,4 +85,4 @@ if (pageResults) {

final String baseUrl = WicketUtils.getGitblitURL(getRequest());
final boolean showGraph = app().settings().getBoolean(Keys.web.showBranchGraph, true);
String baseUrl = WicketUtils.getGitblitURL(getRequest());
boolean showGraph = app().settings().getBoolean(Keys.web.showBranchGraph, true);

@@ -109,4 +112,12 @@ MarkupContainer graph = new WebMarkupContainer("graph");

final int hashLen = app().settings().getInteger(Keys.web.shortCommitIdLength, 6);
ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
DataView<RevCommit> logView = new DataView<RevCommit>("commit", dp) {
List<RepositoryCommit> repoCommits = new ArrayList<>(commits.size());
for (RevCommit c : commits) {
RepositoryCommit repoCommit = new RepositoryCommit(repositoryName, "", c);
if (allRefs.containsKey(c)) {
repoCommit.setRefs(allRefs.get(c));
}
repoCommits.add(repoCommit);
}
ListDataProvider<RepositoryCommit> dp = new ListDataProvider<RepositoryCommit>(repoCommits);
DataView<RepositoryCommit> logView = new DataView<RepositoryCommit>("commit", dp) {
private static final long serialVersionUID = 1L;

@@ -116,5 +127,5 @@ int counter;

@Override
public void populateItem(final Item<RevCommit> item) {
final RevCommit entry = item.getModelObject();
final Date date = JGitUtils.getAuthorDate(entry);
public void populateItem(final Item<RepositoryCommit> item) {
final RepositoryCommit entry = item.getModelObject();
final Date date = entry.getAuthorIdent().getWhen();
final boolean isMerge = entry.getParentCount() > 1;

@@ -142,3 +153,3 @@

String trimmedMessage = shortMessage;
if (allRefs.containsKey(entry.getId())) {
if (!ArrayUtils.isEmpty(entry.getRefs())) {
trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG_REFS);

@@ -156,3 +167,3 @@ } else {

item.add(new RefsPanel("commitRefs", repositoryName, entry, allRefs));
item.add(new RefsPanel("commitRefs", repositoryName, entry.getRefs()));

@@ -159,0 +170,0 @@ // commit hash link

@@ -18,2 +18,3 @@ /*

import java.util.ArrayList;
import java.util.Date;

@@ -35,2 +36,4 @@ import java.util.List;

import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryCommit;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.JGitUtils;

@@ -48,3 +51,3 @@ import com.gitblit.utils.StringUtils;

private boolean hasMore;
private final boolean hasMore;

@@ -63,3 +66,3 @@ public SearchPanel(String wicketId, final String repositoryName, final String objectId,

final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs);
Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs);
List<RevCommit> commits;

@@ -85,4 +88,12 @@ if (pageResults) {

ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
DataView<RevCommit> searchView = new DataView<RevCommit>("commit", dp) {
List<RepositoryCommit> repoCommits = new ArrayList<>(commits.size());
for (RevCommit c : commits) {
RepositoryCommit repoCommit = new RepositoryCommit(repositoryName, "", c);
if (allRefs.containsKey(c)) {
repoCommit.setRefs(allRefs.get(c));
}
repoCommits.add(repoCommit);
}
ListDataProvider<RepositoryCommit> dp = new ListDataProvider<RepositoryCommit>(repoCommits);
DataView<RepositoryCommit> searchView = new DataView<RepositoryCommit>("commit", dp) {
private static final long serialVersionUID = 1L;

@@ -92,5 +103,5 @@ int counter;

@Override
public void populateItem(final Item<RevCommit> item) {
final RevCommit entry = item.getModelObject();
final Date date = JGitUtils.getAuthorDate(entry);
public void populateItem(final Item<RepositoryCommit> item) {
final RepositoryCommit entry = item.getModelObject();
final Date date = entry.getAuthorIdent().getWhen();

@@ -116,3 +127,3 @@ item.add(WicketUtils.createDateLabel("commitDate", date, getTimeZone(), getTimeUtils()));

String trimmedMessage = shortMessage;
if (allRefs.containsKey(entry.getId())) {
if (!ArrayUtils.isEmpty(entry.getRefs())) {
trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG_REFS);

@@ -130,3 +141,3 @@ } else {

item.add(new RefsPanel("commitRefs", repositoryName, entry, allRefs));
item.add(new RefsPanel("commitRefs", repositoryName, entry.getRefs()));

@@ -133,0 +144,0 @@ item.add(new BookmarkablePageLink<Void>("commit", CommitPage.class, WicketUtils

@@ -121,3 +121,3 @@ /*

addKeyForm.add(new TextOption("addKeyComment",
getString("gb.comment"),
getString("gb.sshKeyComment"),
getString("gb.sshKeyCommentDescription"),

@@ -124,0 +124,0 @@ "span5",

@@ -61,3 +61,3 @@ /*

private final Logger log = LoggerFactory.getLogger(SessionlessForm.class);
private transient Logger logger;

@@ -122,3 +122,6 @@ /**

// parameter name, skip embedding a hidden value
log.warn(MessageFormat.format("Skipping page parameter \"{0}\" from sessionless form hidden fields because it collides with a form child wicket:id", key));
logger().warn(
MessageFormat
.format("Skipping page parameter \"{0}\" from sessionless form hidden fields because it collides with a form child wicket:id",
key));
continue;

@@ -161,2 +164,9 @@ }

}
private Logger logger() {
if (logger == null) {
logger = LoggerFactory.getLogger(SessionlessForm.class);
}
return logger;
}
}

@@ -29,2 +29,3 @@ /*

import com.gitblit.utils.TimeUtilsTest;
import org.eclipse.jgit.api.Git;

@@ -31,0 +32,0 @@ import org.eclipse.jgit.lib.Repository;

/*
* Copyright 2011 gitblit.com.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gitblit.tests;
import java.util.Date;
import org.junit.Test;
import com.gitblit.utils.TimeUtils;
public class TimeUtilsTest extends GitblitUnitTest {
private Date offset(long subtract) {
return new Date(System.currentTimeMillis() - subtract);
}
@Test
public void testBasicTimeFunctions() throws Exception {
assertEquals(2, TimeUtils.minutesAgo(offset(2 * TimeUtils.MIN), false));
assertEquals(3, TimeUtils.minutesAgo(offset((2 * TimeUtils.MIN) + (35 * 1000L)), true));
assertEquals(2, TimeUtils.hoursAgo(offset(2 * TimeUtils.ONEHOUR), false));
assertEquals(3, TimeUtils.hoursAgo(offset(5 * TimeUtils.HALFHOUR), true));
assertEquals(4, TimeUtils.daysAgo(offset(4 * TimeUtils.ONEDAY)));
}
@Test
public void testToday() throws Exception {
assertTrue(TimeUtils.isToday(new Date(), null));
}
@Test
public void testYesterday() throws Exception {
assertTrue(TimeUtils.isYesterday(offset(TimeUtils.ONEDAY), null));
}
@Test
public void testDurations() throws Exception {
TimeUtils timeUtils = new TimeUtils();
assertEquals("1 day", timeUtils.duration(1));
assertEquals("5 days", timeUtils.duration(5));
assertEquals("3 months", timeUtils.duration(75));
assertEquals("12 months", timeUtils.duration(364));
assertEquals("1 year", timeUtils.duration(365 + 0));
assertEquals("1 year", timeUtils.duration(365 + 10));
assertEquals("1 year, 1 month", timeUtils.duration(365 + 15));
assertEquals("1 year, 1 month", timeUtils.duration(365 + 30));
assertEquals("1 year, 1 month", timeUtils.duration(365 + 44));
assertEquals("1 year, 2 months", timeUtils.duration(365 + 45));
assertEquals("1 year, 2 months", timeUtils.duration(365 + 60));
assertEquals("2 years", timeUtils.duration(2 * 365 + 0));
assertEquals("2 years", timeUtils.duration(2 * 365 + 10));
assertEquals("2 years, 1 month", timeUtils.duration(2 * 365 + 15));
assertEquals("2 years, 1 month", timeUtils.duration(2 * 365 + 30));
assertEquals("2 years, 1 month", timeUtils.duration(2 * 365 + 44));
assertEquals("2 years, 2 months", timeUtils.duration(2 * 365 + 45));
assertEquals("2 years, 2 months", timeUtils.duration(2 * 365 + 60));
}
@Test
public void testTimeAgo() throws Exception {
// standard time ago tests
TimeUtils timeUtils = new TimeUtils();
assertEquals("just now", timeUtils.timeAgo(offset(1 * TimeUtils.MIN)));
assertEquals("60 mins ago", timeUtils.timeAgo(offset(60 * TimeUtils.MIN)));
assertEquals("2 hours ago", timeUtils.timeAgo(offset(120 * TimeUtils.MIN)));
assertEquals("15 hours ago", timeUtils.timeAgo(offset(15 * TimeUtils.ONEHOUR)));
assertEquals("yesterday", timeUtils.timeAgo(offset(24 * TimeUtils.ONEHOUR)));
assertEquals("2 days ago", timeUtils.timeAgo(offset(2 * TimeUtils.ONEDAY)));
assertEquals("5 weeks ago", timeUtils.timeAgo(offset(35 * TimeUtils.ONEDAY)));
assertEquals("3 months ago", timeUtils.timeAgo(offset(84 * TimeUtils.ONEDAY)));
assertEquals("3 months ago", timeUtils.timeAgo(offset(95 * TimeUtils.ONEDAY)));
assertEquals("4 months ago", timeUtils.timeAgo(offset(104 * TimeUtils.ONEDAY)));
assertEquals("1 year ago", timeUtils.timeAgo(offset(365 * TimeUtils.ONEDAY)));
assertEquals("13 months ago", timeUtils.timeAgo(offset(395 * TimeUtils.ONEDAY)));
assertEquals("2 years ago", timeUtils.timeAgo(offset((2 * 365 + 30) * TimeUtils.ONEDAY)));
// css class tests
assertEquals("age0", timeUtils.timeAgoCss(offset(1 * TimeUtils.MIN)));
assertEquals("age0", timeUtils.timeAgoCss(offset(60 * TimeUtils.MIN)));
assertEquals("age1", timeUtils.timeAgoCss(offset(120 * TimeUtils.MIN)));
assertEquals("age1", timeUtils.timeAgoCss(offset(24 * TimeUtils.ONEHOUR)));
assertEquals("age2", timeUtils.timeAgoCss(offset(2 * TimeUtils.ONEDAY)));
}
@Test
public void testFrequency() {
assertEquals(5, TimeUtils.convertFrequencyToMinutes("2 mins", 5));
assertEquals(10, TimeUtils.convertFrequencyToMinutes("10 mins", 5));
assertEquals(600, TimeUtils.convertFrequencyToMinutes("10 hours", 5));
assertEquals(14400, TimeUtils.convertFrequencyToMinutes(" 10 days ", 5));
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet