5 files deleted
65 files added
142 files modified
| | |
| | | <classpathentry kind="lib" path="ext/log4j-1.2.17.jar" sourcepath="ext/src/log4j-1.2.17.jar" /> |
| | | <classpathentry kind="lib" path="ext/slf4j-api-1.7.5.jar" sourcepath="ext/src/slf4j-api-1.7.5.jar" /> |
| | | <classpathentry kind="lib" path="ext/slf4j-log4j12-1.7.5.jar" sourcepath="ext/src/slf4j-log4j12-1.7.5.jar" /> |
| | | <classpathentry kind="lib" path="ext/mail-1.4.3.jar" sourcepath="ext/src/mail-1.4.3.jar" /> |
| | | <classpathentry kind="lib" path="ext/javax.mail-1.5.1.jar" sourcepath="ext/src/javax.mail-1.5.1.jar" /> |
| | | <classpathentry kind="lib" path="ext/javax.servlet-api-3.1.0.jar" sourcepath="ext/src/javax.servlet-api-3.1.0.jar" /> |
| | | <classpathentry kind="lib" path="ext/jetty-all-9.1.4.v20140401.jar" sourcepath="ext/src/jetty-all-9.1.4.v20140401.jar" /> |
| | | <classpathentry kind="lib" path="ext/wicket-1.4.21.jar" sourcepath="ext/src/wicket-1.4.21.jar" /> |
| | |
| | | <classpathentry kind="lib" path="ext/jedis-2.3.1.jar" sourcepath="ext/src/jedis-2.3.1.jar" /> |
| | | <classpathentry kind="lib" path="ext/commons-pool2-2.0.jar" sourcepath="ext/src/commons-pool2-2.0.jar" /> |
| | | <classpathentry kind="lib" path="ext/pf4j-0.8.0.jar" sourcepath="ext/src/pf4j-0.8.0.jar" /> |
| | | <classpathentry kind="lib" path="ext/tika-core-1.5.jar" sourcepath="ext/src/tika-core-1.5.jar" /> |
| | | <classpathentry kind="lib" path="ext/junit-4.11.jar" sourcepath="ext/src/junit-4.11.jar" /> |
| | | <classpathentry kind="lib" path="ext/hamcrest-core-1.3.jar" sourcepath="ext/src/hamcrest-core-1.3.jar" /> |
| | | <classpathentry kind="lib" path="ext/selenium-java-2.28.0.jar" sourcepath="ext/src/selenium-java-2.28.0.jar" /> |
| | |
| | | /*.sh |
| | | /*.factorypath |
| | | /src/main/dagger |
| | | /src/main/java/.idea |
| | | /**/.idea |
| | | /**/init.lua |
| | | /**/session |
New file |
| | |
| | | [submodule "src/main/distrib/data/gitignore"] |
| | | path = src/main/distrib/data/gitignore |
| | | url = https://github.com/github/gitignore.git |
| | |
| | | [[src/site/setup_war.mkd]]
|
| | | [[src/site/upgrade_war.mkd]]
|
| | |
|
| | | ### Gitblit Express for OpenShift
|
| | |
|
| | | [[src/site/setup_express.mkd]]
|
| | | [[src/site/upgrade_express.mkd]]
|
| | |
|
| | | ### General Configuration & Administration
|
| | |
|
| | | [[src/site/setup_authentication.mkd]]
|
| | |
| | | Gitblit
|
| | | =================
|
| | |
|
| | | Gitblit is an open source, pure Java Git solution for managing, viewing, and serving [Git](http://git-scm.com) repositories.
|
| | | Gitblit is an open source, pure Java Git solution for managing, viewing, and serving [Git](http://git-scm.com) repositories. It can serve repositories over the GIT, HTTP, and SSH transports; it can authenticate against multiple providers; and it allows you to get up-and-running with an attractive, capable Git server in less than 5 minutes.
|
| | |
|
| | | More information about Gitblit can be found [here](http://gitblit.com).
|
| | |
|
| | | [  ](https://bintray.com/gitblit/releases/stable/_latestVersion)
|
| | | <a href='https://bintray.com/gitblit/releases/gitblit/_latestVersion'><img src='https://api.bintray.com/packages/gitblit/releases/gitblit/images/download.png'></a>
|
| | |
|
| | | License
|
| | | -------
|
| | |
| | | Getting help
|
| | | ------------
|
| | |
|
| | | Read the online documentation available at the [Gitblit website](http://gitblit.com)
|
| | | Issues, binaries, & sources @ [Google Code](http://code.google.com/p/gitblit)
|
| | | | Source | Location |
|
| | | | ------------- |--------------------------------------------------------|
|
| | | | Documentation | [Gitblit website](http://gitblit.com) |
|
| | | | Issues | [Google Code](http://code.google.com/p/gitblit) |
|
| | | | Forums | [Google Groups](https://groups.google.com/forum/#!forum/gitblit) |
|
| | | | Twitter | @gitblit or @jamesmoger |
|
| | | | Google+ | +gitblit or +jamesmoger |
|
| | |
|
| | | Contributing
|
| | | ------------
|
| | |
|
| | | GitHub pull requests or Gitblit Tickets are preferred. Any contributions must be distributed under the terms of the [Apache Software Foundation license, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
| | |
|
| | | **Workflow**
|
| | |
|
| | | Gitblit practices the [git-flow][1] branching model.
|
| | |
|
| | | - **master** is the current stable release + fixes accumulated since release.
|
| | | - **develop** is the integration branch for the next major release.
|
| | | - **ticket/N** are feature or hotfix branches to be merged to **master** or **develop**, as appropriate.
|
| | |
|
| | | **Feature Development**
|
| | |
|
| | | Development of new features is mostly done using [Gitblit Tickets][2] hosted at [dev.gitblit.com][3]. This allows continuous dogfooding and improvement of Gitbit's own issue-tracker and pull-request mechanism.
|
| | |
|
| | | **Release Planning**
|
| | |
|
| | | Release planning is mostly done using Gitblit Milestones and Gitblit Tickets hosted at [dev.gitblit.com][3].
|
| | |
|
| | | **Releasing**
|
| | |
|
| | | When Gitblit is preparing for a release, a **release-{milestone}** branch will be created, tested, & fixed until it is ready to be merged to **master** and tagged as the next major release. After the release is tagged, the **release-{milestone}** branch will also be merged back into **develop** and then the release branch will be removed.
|
| | |
|
| | | Building Gitblit
|
| | | ----------------
|
| | |
|
| | | Gitblit uses submodules.
|
| | | Make sure to clone using `--recursive` OR to execute `git submodule update --init --recursive`.
|
| | |
|
| | | [Eclipse](http://eclipse.org) is recommended for development as the project settings are preconfigured.
|
| | |
|
| | | 1. Import the gitblit project into your Eclipse workspace.
|
| | |
| | | Building Tips & Tricks
|
| | | ----------------------
|
| | | 1. If you are running Ant from an ANSI-capable console, consider setting the `MX_COLOR` environment variable before executing Ant.<pre>set MX_COLOR=true</pre>
|
| | | 2. The build script will honor your Maven proxy settings. If you need to fine-tune this, please review the [settings.moxie](http://gitblit.github.io/moxie/settings.html) documentation. |
| | | 2. The build script will honor your Maven proxy settings. If you need to fine-tune this, please review the [settings.moxie](http://gitblit.github.io/moxie/settings.html) documentation.
|
| | |
|
| | | [1]: http://nvie.com/posts/a-successful-git-branching-model
|
| | | [2]: http://gitblit.com/tickets_overview.html
|
| | | [3]: https://dev.gitblit.com
|
| | |
| | | # |
| | | |
| | | # Specify minimum Moxie version required to build |
| | | requires: 0.9.1 |
| | | requires: 0.9.2 |
| | | |
| | | # Project Metadata |
| | | name: Gitblit |
| | | description: pure Java Git solution |
| | | groupId: com.gitblit |
| | | artifactId: gitblit |
| | | version: 1.5.2-SNAPSHOT |
| | | version: 1.6.0 |
| | | inceptionYear: 2011 |
| | | |
| | | # Current stable release |
| | | releaseVersion: 1.5.1 |
| | | releaseDate: 2014-05-07 |
| | | releaseVersion: 1.6.0 |
| | | releaseDate: 2014-06-16 |
| | | |
| | | # Project urls |
| | | url: 'http://gitblit.com' |
| | |
| | | - compile 'log4j:log4j:1.2.17' :war :fedclient :authority |
| | | - compile 'org.slf4j:slf4j-api:1.7.5' :war :fedclient :authority |
| | | - compile 'org.slf4j:slf4j-log4j12:1.7.5' :war :fedclient :authority |
| | | - compile 'javax.mail:mail:1.4.3' :war :authority |
| | | - compile 'com.sun.mail:javax.mail:1.5.1' :war :authority |
| | | - compile 'javax.servlet:javax.servlet-api:3.1.0' :fedclient |
| | | - compile 'org.eclipse.jetty.aggregate:jetty-all:${jetty.version}' @jar |
| | | - compile 'org.apache.wicket:wicket:${wicket.version}' :war !org.mockito |
| | |
| | | - compile 'commons-codec:commons-codec:1.7' :war |
| | | - compile 'redis.clients:jedis:2.3.1' :war |
| | | - compile 'ro.fortsoft.pf4j:pf4j:0.8.0' :war |
| | | - compile 'org.apache.tika:tika-core:1.5' :war |
| | | - test 'junit' |
| | | # Dependencies for Selenium web page testing |
| | | - test 'org.seleniumhq.selenium:selenium-java:${selenium.version}' @jar |
| | |
| | | documentation @ http://gitblit.github.io/moxie
|
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| | | -->
|
| | | <property name="moxie.version" value="0.9.1" />
|
| | | <property name="moxie.version" value="0.9.2" />
|
| | | <property name="moxie.url" value="http://gitblit.github.io/moxie/maven" />
|
| | | <property name="moxie.jar" value="moxie-toolkit-${moxie.version}.jar" />
|
| | | <property name="moxie.dir" value="${user.home}/.moxie" />
|
| | |
| | | <property name="manager.zipfile" value="manager-${project.version}.zip" />
|
| | | <property name="authority.zipfile" value="authority-${project.version}.zip" />
|
| | | <property name="gbapi.zipfile" value="gbapi-${project.version}.zip" />
|
| | | <property name="express.zipfile" value="express-${project.version}.zip" />
|
| | | <property name="maven.directory" value="${basedir}/../gitblit-maven" />
|
| | |
|
| | | <!-- Download links -->
|
| | |
| | | <property name="go.dir" value="${project.outputDirectory}/go" />
|
| | | <delete dir="${go.dir}" />
|
| | |
|
| | | <local name="webinf" />
|
| | | <property name="webinf" value="${project.compileOutputDirectory}/WEB-INF" />
|
| | |
|
| | | <prepareDataDirectory toDir="${go.dir}/data" />
|
| | | |
| | | <!-- Copy the web.xml from the prototype web.xml -->
|
| | | <copy todir="${webinf}" overwrite="true">
|
| | | <fileset file="${project.src.dir}/WEB-INF/web.xml" />
|
| | | <filterset>
|
| | | <filter token="gb.version" value="${project.version}" />
|
| | | </filterset>
|
| | | </copy>
|
| | |
|
| | | <!-- Build jar -->
|
| | | <mx:jar destfile="${go.dir}/gitblit.jar" includeresources="true">
|
| | |
| | | <!-- Prepare the data directory -->
|
| | | <prepareDataDirectory toDir="${webinf}/data" />
|
| | |
|
| | | <!-- Build the WAR web.xml from the prototype web.xml -->
|
| | | <mx:webxml sourcefile="${project.src.dir}/WEB-INF/web.xml" destfile="${webinf}/web.xml">
|
| | | <replace token="@gb.version@" value="${project.version}" />
|
| | | </mx:webxml>
|
| | | <!-- Copy the web.xml from the prototype web.xml -->
|
| | | <copy todir="${webinf}" overwrite="true">
|
| | | <fileset file="${project.src.dir}/WEB-INF/web.xml" />
|
| | | <filterset>
|
| | | <filter token="gb.version" value="${project.version}" />
|
| | | </filterset>
|
| | | </copy>
|
| | |
|
| | | <!-- Gitblit jar -->
|
| | | <mx:jar destfile="${webinf}/lib/gitblit.jar" includeresources="false" />
|
| | |
| | | <!-- Cleanup -->
|
| | | <delete file="${project.targetDirectory}/fedclient.jar" />
|
| | |
|
| | | </target>
|
| | |
|
| | |
|
| | | <!-- |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| | | Build a Gitblit filesystem for deployment to RedHat OpenShift Express
|
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| | | -->
|
| | | <target name="buildExpress" depends="compile" description="Build exploded WAR file suitable for deployment to OpenShift Express">
|
| | | <echo>Building Gitblit Express for RedHat OpenShift ${project.version}</echo>
|
| | | |
| | | <local name="express.dir" />
|
| | | <property name="express.dir" value="${project.outputDirectory}/express" /> |
| | | <delete dir="${express.dir}" />
|
| | | |
| | | <!-- Create the OpenShift filesystem -->
|
| | | <local name="deployments.root" />
|
| | | <property name="deployments.root" value="${express.dir}/deployments/ROOT.war"/>
|
| | | <mkdir dir="${deployments.root}" />
|
| | | <touch file="${express.dir}/deployments/ROOT.war.dodeploy" />
|
| | |
|
| | | <local name="webinf" />
|
| | | <property name="webinf" value="${deployments.root}/WEB-INF" />
|
| | |
|
| | | <!-- Prepare the data directory -->
|
| | | <prepareDataDirectory toDir="${webinf}/data" />
|
| | | |
| | | <!-- Build the Express web.xml from the prototype web.xml and gitblit.properties -->
|
| | | <!-- THIS FILE IS NOT OVERRIDDEN ONCE IT IS BUILT!!! -->
|
| | | <mx:webxml sourcefile="${project.src.dir}/WEB-INF/web.xml" destfile="${webinf}/web.xml"
|
| | | propertiesFile="${project.distrib.dir}/data/gitblit.properties"
|
| | | skip="server.*">
|
| | | <replace token="@gb.version@" value="${project.version}" />
|
| | | </mx:webxml>
|
| | |
|
| | | <!-- Gitblit classes -->
|
| | | <mx:jar destfile="${webinf}/lib/gitblit.jar" includeresources="false" />
|
| | |
|
| | | <!-- Build Express Zip file -->
|
| | | <mx:zip basedir="${express.dir}" destfile="${project.targetDirectory}/${express.zipfile}">
|
| | | <fileset dir="${basedir}">
|
| | | <include name="LICENSE" />
|
| | | <include name="NOTICE" />
|
| | | </fileset>
|
| | | <!-- README -->
|
| | | <zipfileset fullpath="README.gitblit" file="${project.siteSourceDirectory}/openshift.mkd" />
|
| | | <!-- resources -->
|
| | | <zipfileset prefix="deployments/ROOT.war" dir="${project.resources.dir}">
|
| | | <exclude name="thumbs.db" />
|
| | | <exclude name="*.mkd" />
|
| | | </zipfileset>
|
| | | <!-- include "war" tagged dependencies -->
|
| | | <dependencies prefix="deployments/ROOT.war/WEB-INF/lib" tag="war" />
|
| | | </mx:zip>
|
| | |
|
| | | </target>
|
| | |
|
| | |
|
| | |
| | | <page name="upgrade WAR" src="upgrade_war.mkd" />
|
| | | </menu>
|
| | | <divider />
|
| | | <menu name="Gitblit Express" pager="true" pagerPlacement="bottom" pagerLayout="justified">
|
| | | <page name="setup Express" src="setup_express.mkd" />
|
| | | <page name="upgrade Express" src="upgrade_express.mkd" />
|
| | | </menu>
|
| | | <divider />
|
| | | <menu name="Server Configuration" pager="true" pagerPlacement="bottom" pagerLayout="justified">
|
| | | <page name="administration" src="administration.mkd" />
|
| | | <page name="authentication" src="setup_authentication.mkd" />
|
| | |
| | | <link name="Gitblit GO (Windows)" src="${gc.url}gitblit-${project.releaseVersion}.zip" />
|
| | | <link name="Gitblit GO (Linux/OSX)" src="${gc.url}gitblit-${project.releaseVersion}.tar.gz" />
|
| | | <link name="Gitblit WAR" src="${gc.url}gitblit-${project.releaseVersion}.war" />
|
| | | <link name="Gitblit Express" src="${gc.url}express-${project.releaseVersion}.zip" />
|
| | | <divider />
|
| | | <link name="Gitblit GO (Docker)" src="https://registry.hub.docker.com/u/jmoger/gitblit/" />
|
| | | <divider />
|
| | | <link name="Plugins Registry" src="http://plugins.gitblit.com" />
|
| | | <divider />
|
| | | <link name="Gitblit Manager" src="${gc.url}manager-${project.releaseVersion}.zip" />
|
| | | <link name="Federation Client" src="${gc.url}fedclient-${project.releaseVersion}.zip" />
|
| | |
| | | <menu name="links">
|
| | | <link name="dev.gitblit.com (self-hosted)" src="https://dev.gitblit.com" />
|
| | | <divider />
|
| | | <link name="Plugin Registry" src="http://plugins.gitblit.com" />
|
| | | <link name="Plugins Registry" src="http://plugins.gitblit.com" />
|
| | | <divider />
|
| | | <link name="Github" src="${project.scmUrl}" />
|
| | | <link name="Issues" src="${project.issuesUrl}" />
|
| | |
| | | Build all binaries and site
|
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| | | -->
|
| | | <target name="buildAll" depends="buildGO,buildWAR,buildExpress,buildFederationClient,buildManager,buildApiLibrary,buildSite" /> |
| | | <target name="buildAll" depends="buildGO,buildWAR,buildFederationClient,buildManager,buildApiLibrary,buildSite" /> |
| | |
|
| | |
|
| | | <!--
|
| | |
| | | <bintrayUpload
|
| | | source="${project.targetDirectory}/${gbapi.zipfile}"
|
| | | target="gbapi-${project.version}.zip" />
|
| | |
|
| | | <!-- Upload Gitblit Express for RedHat OpenShift -->
|
| | | <bintrayUpload
|
| | | source="${project.targetDirectory}/${express.zipfile}" |
| | | target="express-${project.version}.zip" />
|
| | |
|
| | | </target>
|
| | |
|
| | |
| | | </filterset>
|
| | | </copy>
|
| | | <chmod file="${recipe}" perm="ugo+rx" />
|
| | | </target>
|
| | |
|
| | | |
| | | <!--
|
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | Prepare for the next point release development cycle.
|
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | -->
|
| | | <target name="nextPointReleaseCycle" depends="prepare" description="prepare for the next point release development cycle">
|
| | | <!-- next cycle -->
|
| | | <mx:version stage="snapshot" incrementNumber="incremental" dryrun="${dryrun}" />
|
| | | <mx:commit showtitle="no">
|
| | | <message>Reset build identifiers for next development cycle</message>
|
| | | <message>Reset build identifiers for next point release cycle</message>
|
| | | </mx:commit>
|
| | | </target>
|
| | |
|
| | |
|
| | | <!--
|
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | Prepare for the next minor release development cycle.
|
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | -->
|
| | | <target name="nextMinorReleaseCycle" depends="prepare" description="prepare for the next minor release development cycle">
|
| | | <!-- next cycle -->
|
| | | <mx:version stage="snapshot" incrementNumber="minor" dryrun="${dryrun}" />
|
| | | <mx:commit showtitle="no">
|
| | | <message>Reset build identifiers for next minor release cycle</message>
|
| | | </mx:commit> |
| | | </target>
|
| | |
|
| | | |
| | | <!--
|
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| | | Build Gitblit Docs
|
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| | |
| | | <menu name="Gitblit WAR" pager="true" pagerPlacement="bottom" pagerLayout="justified">
|
| | | <page name="setup WAR" src="setup_war.mkd" />
|
| | | <page name="upgrade WAR" src="upgrade_war.mkd" />
|
| | | </menu>
|
| | | <divider />
|
| | | <menu name="Gitblit Express" pager="true" pagerPlacement="bottom" pagerLayout="justified">
|
| | | <page name="setup Express" src="setup_express.mkd" />
|
| | | <page name="upgrade Express" src="upgrade_express.mkd" />
|
| | | </menu>
|
| | | <divider />
|
| | | <menu name="Server Configuration" pager="true" pagerPlacement="bottom" pagerLayout="justified">
|
| | |
| | | <menu name="links">
|
| | | <link name="dev.gitblit.com (self-hosted)" src="https://dev.gitblit.com" />
|
| | | <divider />
|
| | | <link name="Plugin Registry" src="http://plugins.gitblit.com" />
|
| | | <link name="Plugins Registry" src="http://plugins.gitblit.com" />
|
| | | <divider />
|
| | | <link name="Github" src="${project.scmUrl}" />
|
| | | <link name="Issues" src="${project.issuesUrl}" />
|
| | |
| | | <include name="subgit.groovy" />
|
| | | </fileset>
|
| | | </copy>
|
| | | <mkdir dir="@{toDir}/gitignore" />
|
| | | <copy todir="@{toDir}/gitignore">
|
| | | <fileset dir="${project.distrib.dir}/data/gitignore"> |
| | | <include name="*.gitignore" />
|
| | | </fileset>
|
| | | </copy>
|
| | | </sequential>
|
| | | </macrodef>
|
| | |
|
| | |
| | | </library> |
| | | </orderEntry> |
| | | <orderEntry type="module-library"> |
| | | <library name="mail-1.4.3.jar"> |
| | | <library name="javax.mail-1.5.1.jar"> |
| | | <CLASSES> |
| | | <root url="jar://$MODULE_DIR$/ext/mail-1.4.3.jar!/" /> |
| | | <root url="jar://$MODULE_DIR$/ext/javax.mail-1.5.1.jar!/" /> |
| | | </CLASSES> |
| | | <JAVADOC /> |
| | | <SOURCES> |
| | | <root url="jar://$MODULE_DIR$/ext/src/mail-1.4.3.jar!/" /> |
| | | <root url="jar://$MODULE_DIR$/ext/src/javax.mail-1.5.1.jar!/" /> |
| | | </SOURCES> |
| | | </library> |
| | | </orderEntry> |
| | |
| | | </SOURCES> |
| | | </library> |
| | | </orderEntry> |
| | | <orderEntry type="module-library"> |
| | | <library name="tika-core-1.5.jar"> |
| | | <CLASSES> |
| | | <root url="jar://$MODULE_DIR$/ext/tika-core-1.5.jar!/" /> |
| | | </CLASSES> |
| | | <JAVADOC /> |
| | | <SOURCES> |
| | | <root url="jar://$MODULE_DIR$/ext/src/tika-core-1.5.jar!/" /> |
| | | </SOURCES> |
| | | </library> |
| | | </orderEntry> |
| | | <orderEntry type="module-library" scope="TEST"> |
| | | <library name="junit-4.11.jar"> |
| | | <CLASSES> |
| | |
| | | #!/bin/bash
|
| | | #
|
| | | # ${project.version} release script
|
| | | #
|
| | |
|
| | | # ensure Maven repository is up-to-date
|
| | | echo ""
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo "Preparing Maven repository"
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo ""
|
| | | cd ${maven.directory}
|
| | | git checkout gh-pages
|
| | | git pull
|
| | | cd ${project.directory}
|
| | |
|
| | | # go back one commit to RELEASE commit
|
| | | echo ""
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo "Checking out ${project.version} RELEASE commit ${project.commitId}"
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo ""
|
| | | git checkout ${project.commitId}
|
| | |
|
| | | # build RELEASE artifacts
|
| | | echo ""
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo "Building ${project.version} RELEASE artifacts"
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo ""
|
| | | ant clean buildAll buildMavenArtifacts
|
| | |
|
| | | # commit all generated artifacts and metadata
|
| | | echo ""
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo "Committing Maven repository ${project.version} RELEASE artifacts"
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo ""
|
| | | cd ${maven.directory}
|
| | | git add .
|
| | | git commit -m "${project.version} artifacts"
|
| | | cd ${project.directory}
|
| | |
|
| | | # upload artifacts
|
| | | echo ""
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo "Uploading ${project.version} artifacts"
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo ""
|
| | | ant publishBinaries
|
| | |
|
| | | # build site, update gh-pages, and ftp upload site to hosting provider
|
| | | echo ""
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo "Building ${project.version} website"
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo ""
|
| | | ant publishSite
|
| | |
|
| | | # return to project master
|
| | | echo ""
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo "Checking out master"
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo ""
|
| | | git checkout master
|
| | |
|
| | | # push Maven repository to origin
|
| | | echo ""
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo "Pushing Maven repository"
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo ""
|
| | | cd ${maven.directory}
|
| | | git push origin gh-pages
|
| | | cd ${project.directory}
|
| | |
|
| | | # push project branches
|
| | | echo ""
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo "Pushing master, gh-pages, and tag ${project.tag}"
|
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
| | | echo ""
|
| | | git push origin master gh-pages tag ${project.tag}
|
| | | #!/bin/bash |
| | | # |
| | | # ${project.version} release script |
| | | # |
| | | |
| | | # ensure Maven repository is up-to-date |
| | | echo "" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "Preparing Maven repository" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "" |
| | | cd ${maven.directory} |
| | | git checkout gh-pages |
| | | git pull |
| | | cd ${project.directory} |
| | | |
| | | # go back one commit to RELEASE commit |
| | | echo "" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "Checking out ${project.version} RELEASE commit ${project.commitId}" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "" |
| | | git checkout ${project.commitId} |
| | | |
| | | # build RELEASE artifacts |
| | | echo "" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "Building ${project.version} RELEASE artifacts" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "" |
| | | ant clean buildAll buildMavenArtifacts |
| | | |
| | | # commit all generated artifacts and metadata |
| | | echo "" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "Committing Maven repository ${project.version} RELEASE artifacts" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "" |
| | | cd ${maven.directory} |
| | | git add . |
| | | git commit -m "${project.version} artifacts" |
| | | cd ${project.directory} |
| | | |
| | | # upload artifacts |
| | | echo "" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "Uploading ${project.version} artifacts" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "" |
| | | ant publishBinaries |
| | | |
| | | # build site, update gh-pages, and ftp upload site to hosting provider |
| | | echo "" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "Building ${project.version} website" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "" |
| | | ant publishSite |
| | | |
| | | # merge to master |
| | | echo "" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "Merging release ${project.version} to master" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "" |
| | | git checkout master |
| | | git merge -m "Merge release ${project.version}" ${project.commitId} |
| | | ant nextPointReleaseCycle |
| | | |
| | | # merge to develop |
| | | echo "" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "Merging release ${project.version} to develop" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "" |
| | | git checkout develop |
| | | git merge -m "Merge release ${project.version}" ${project.commitId} |
| | | ant nextMinorReleaseCycle |
| | | |
| | | # push Maven repository to origin |
| | | echo "" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "Pushing Maven repository" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "" |
| | | cd ${maven.directory} |
| | | git push origin gh-pages |
| | | cd ${project.directory} |
| | | |
| | | # push project branches |
| | | echo "" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "Pushing master, develop, gh-pages, and tag ${project.tag}" |
| | | echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" |
| | | echo "" |
| | | git push origin master develop gh-pages tag ${project.tag} |
| | |
| | | # |
| | | # ${project.version} release |
| | | # 1.6.0 release |
| | | # |
| | | r24: { |
| | | title: ${project.name} ${project.version} released |
| | | id: ${project.version} |
| | | date: ${project.buildDate} |
| | | note: ~ |
| | | title: Gitblit 1.6.0 released |
| | | id: 1.6.0 |
| | | date: 2014-06-16 |
| | | note: '' |
| | | The next major release (v1.7.0) will focus on: |
| | | * ticket-75: making projects more useful including the concept of project ownership |
| | | |
| | | This improvement will require a NON-BACKWARDS-COMPATIBLE migration of repository ownership from the RpeositoryModel to the UserModel |
| | | |
| | | * ticket-55: facilitating usage of tickets & git-flow in the web ui |
| | | '' |
| | | html: ~ |
| | | text: ~ |
| | | text: '' |
| | | Highlights: |
| | | |
| | | * My Tickets page |
| | | * User Preferences web ui |
| | | * SSH key management web ui |
| | | * Basic CRUD pages for ticket milestones |
| | | * Overhaul repository creation, editing, and empty repository pages |
| | | |
| | | If you are upgrading, you might consider copying the data/gitignore folder to your ${baseFolder} to allow selection & injection of a .gitignore when creating a repository. |
| | | |
| | | The OpenShift Express build has been dropped. You can deploy GO or WAR on Express so this build is no longer necessary. |
| | | '' |
| | | security: ~ |
| | | fixes: ~ |
| | | changes: ~ |
| | | additions: ~ |
| | | dependencyChanges: ~ |
| | | contributors: ~ |
| | | fixes: |
| | | - Allow ticket responsible selection if anonymous push is enabled (issue-425, ticket-71) |
| | | - Fix failure to generate SSH server keys on ARM (issue-426, ticket-70) |
| | | - Fix flotr2 chart generation failure if a label contained a single-quote (ticket-77) |
| | | - Fix repository cache refresh after ref deletion/addition (issue-433, ticket-82) |
| | | - Fixed cache miss on repository model retrieval (pr-185, ticket-83) |
| | | - Fixed GitBlit static singleton reference in localclone.groovy (issue-436, ticket-84) |
| | | - Removed Ticket responsible team permission exclusion (ticket-87) |
| | | - Fixed SSH daemon thread exhaustion (ticket-89) |
| | | - Fixed Ticket responsible selections not considering the AUTHENTICATED authorization control (ticket-91) |
| | | - Fixed invalid generated SSH url for port 22 (issue-444, ticket-98) |
| | | - Fix cloning repositories with `+` in their names. (revert pr-136, issue-362, ticket-100) |
| | | - Fixed NPE in GitblitClient (ticket-102) |
| | | changes: |
| | | - Split the pages servlet into a raw servlet and a pages servlet. All raw links now use the raw servlet (issue-413, ticket-49) |
| | | - Drop deprecated --set-upstream syntax for -u (ticket-59) |
| | | - BARNUM: Prune deleted branches on fetch (git fetch -p) (ticket-60) |
| | | - BARNUM: Create ticket/N instead of topic/N for pt start N (ticket-61) |
| | | - Move repository deletion functions to the edit repository page AND allow deletion to be disabled (pr-180, ticket-67) |
| | | - Update the Korean translation (pr-184, ticket-69) |
| | | - Update the Dutch translation (pr-191) |
| | | - Overhaul the EmptyRepositoryPage (ticket-73) |
| | | - Overhauled the edit repository page (ticket-76) |
| | | - Process bugtraq links in the ticket description and comments (ticket-78) |
| | | - Exclude personal repositories from the repositories list, by default (issue-419, ticket-95) |
| | | additions: |
| | | - Add My Tickets page (issue-215, ticket-15) |
| | | - Added CRUD functionality for Ticket Milestones (ticket-17) |
| | | - Implemented Ticket migration tool to move between backends (ticket-19) |
| | | - Added extension points for top nav links, root-level pages, repository nav links, user menu links, and http request filters (ticket-23) |
| | | - Added an editor panel in the user profile page to manipulate preferences (issue-108, issue-424, ticket-64) |
| | | - Added an editor panel in the user profile page to manipulate public SSH keys (ticket-64) |
| | | - Add FORK_REPOSITORY RPC request type (issue-371, pr-161, ticket-65) |
| | | - Add object type (ot) parameter for RSS queries to retrieve tag details (pr-165, ticket-66) |
| | | - Add setting to allow STARTTLS without requiring SMTPS (pr-183) |
| | | - Simplified repository creation, offer simple README generation, and insertion of a pre-defined .gitignore file (ticket-76) |
| | | - Added an extension point for monitoring onStartup and onShutdown (ticket-79) |
| | | - Tag server-side merges when incremental push tags are enabled (issue-432, ticket-85) |
| | | - Add a user preference for the clone transport (ticket-90) |
| | | - Add setting to control default thread pool size for miscellaneous background tasks (ticket-92) |
| | | - Add Norwegian transation (pr-186) |
| | | - Add German translation (pr-192) |
| | | - Add Italian translation (pr-196) |
| | | dependencyChanges: |
| | | - Update to javax.mail 1.5.1 (issue-417, ticket-58) |
| | | contributors: |
| | | - James Moger |
| | | - David Ostrovsky |
| | | - Manisha Gayathri |
| | | - Gerard Smyth |
| | | - Christian Buisson |
| | | - Berke Viktor |
| | | - Marcus Hunger |
| | | - Matthias Cullmann |
| | | - Emmeran Seehuber |
| | | - Sascha Vogt |
| | | - Carsten Lenz |
| | | - Matthias Sohn |
| | | - Leif Jantzen |
| | | - Stardrad Yin |
| | | - Jeroen Baten |
| | | - Dongsu Kim |
| | | - Karanbir Singh |
| | | - Tamás Papp |
| | | - GianMaria Romanato |
| | | settings: |
| | | - { name: 'web.allowDeletingNonEmptyRepositories', defaultValue: 'true' } |
| | | - { name: 'web.includePersonalRepositories', defaultValue: 'false' } |
| | | - { name: 'mail.starttls', defaultValue: 'false' } |
| | | - { name: 'execution.defaultThreadPoolSize', defaultValue: '1' } |
| | | - { name: 'git.gitignoreFolder', defaultValue: '${baseFolder}/gitignore' } |
| | | } |
| | | |
| | | # |
| | |
| | | - Fix transport determination for SSH urls served on port 22 (issue-421, ticket-63) |
| | | changes: |
| | | - improve French translation (pr-176) |
| | | - simplify current plugin release detection and ignore the currentRelease registry field |
| | | additions: |
| | | - added TortoiseGit client app menu (pr-182) |
| | | - simplify current plugin release detection and ignore the currentRelease registry field |
| | | - split pages servlet into two servlets (issue-413) |
| | | additions: ~ |
| | | dependencyChanges: |
| | | - update to Apache MINA/SSHD 0.11.0 (issue-410) |
| | | - added Apache Tiki 1.5 (issue-413) |
| | | contributors: |
| | | - James Moger |
| | | - Julien Kirch |
| | |
| | | - James Moger |
| | | } |
| | | |
| | | snapshot: &r24 |
| | | release: &r23 |
| | | releases: &r[1..23] |
| | | snapshot: ~ |
| | | release: &r24 |
| | | releases: &r[1..24] |
| | |
| | | # SINCE 1.4.0
|
| | | git.createRepositoriesShared = false
|
| | |
|
| | | # Directory for gitignore templates used during repository creation.
|
| | | #
|
| | | # SINCE 1.6.0
|
| | | git.gitignoreFolder = ${baseFolder}/gitignore
|
| | |
|
| | | # Enable JGit-based garbage collection. (!!EXPERIMENTAL!!)
|
| | | #
|
| | | # USE AT YOUR OWN RISK!
|
| | |
| | | # SINCE 1.5.0
|
| | | plugins.registry = http://plugins.gitblit.com/plugins.json
|
| | |
|
| | | # Number of threads used to handle miscellaneous tasks in the background.
|
| | | #
|
| | | # SINCE 1.6.0
|
| | | # RESTART REQUIRED
|
| | | execution.defaultThreadPoolSize = 1
|
| | |
|
| | | #
|
| | | # Groovy Integration
|
| | | #
|
| | |
| | | #
|
| | | # SINCE 0.5.0
|
| | | web.allowCookieAuthentication = true
|
| | |
|
| | | # Allow deletion of non-empty repositories. This is enforced for all delete vectors.
|
| | | #
|
| | | # SINCE 1.6.0
|
| | | web.allowDeletingNonEmptyRepositories = true
|
| | |
|
| | | # Setting to include personal repositories in the main repositories list.
|
| | | #
|
| | | # SINCE 1.6.0
|
| | | web.includePersonalRepositories = false
|
| | |
|
| | | # Config file for storing project metadata
|
| | | #
|
| | |
| | | # use SMTPs flag
|
| | | mail.smtps = false
|
| | |
|
| | | # use STARTTLS flag
|
| | | #
|
| | | # SINCE 1.6.0
|
| | | mail.starttls = false
|
| | |
|
| | | # if your smtp server requires authentication, supply the credentials here
|
| | | #
|
| | | # SINCE 0.6.0
|
| | |
| | | realm.redmine.url = http://example.com/redmine
|
| | |
|
| | | #
|
| | | # Server Settings
|
| | | # Gitblit GO Server Settings
|
| | | # The following settings only affect the integrated GO variant.
|
| | | #
|
| | |
|
| | | # The temporary folder to decompress the embedded gitblit webapp.
|
| | |
| | | # BASEFOLDER
|
| | | server.tempFolder = ${baseFolder}/temp
|
| | |
|
| | | # Specify the maximum number of concurrent http/https worker threads to allow. |
| | | # Specify the maximum number of concurrent http/https Jetty worker
|
| | | # threads to allow. This setting does not affect other threaded
|
| | | # daemons and components of Gitblit.
|
| | | #
|
| | | # SINCE 1.3.0
|
| | | # RESTART REQUIRED
|
New file |
| | |
| | | Subproject commit 097db81c08b138dea7cb031eb18eeb16afe44bdf |
New file |
| | |
| | | #!/bin/bash |
| | | # -------------------------------------------------------------------------- |
| | | # This is for migrating Tickets from one service to another. |
| | | # |
| | | # usage: |
| | | # |
| | | # migrate-tickets.sh <outputservice> <baseFolder> |
| | | # |
| | | # -------------------------------------------------------------------------- |
| | | |
| | | if [[ -z $1 || -z $2 ]]; then |
| | | echo "Please specify the output ticket service and your baseFolder!"; |
| | | echo ""; |
| | | echo "usage:"; |
| | | echo " migrate-tickets <outputservice> <baseFolder>"; |
| | | echo ""; |
| | | exit 1; |
| | | fi |
| | | |
| | | java -cp gitblit.jar:./ext/* com.gitblit.MigrateTickets $1 --baseFolder $2 |
| | | |
| | |
| | | # |
| | | # -------------------------------------------------------------------------- |
| | | |
| | | if [ -z $1 ]; then |
| | | if [[ -z $1 ]]; then |
| | | echo "Please specify your baseFolder!"; |
| | | echo ""; |
| | | echo "usage:"; |
New file |
| | |
| | | @REM --------------------------------------------------------------------------
|
| | | @REM This is for migrating Tickets from one service to another.
|
| | | @REM
|
| | | @REM usage:
|
| | | @REM migrate-tickets <outputservice> <baseFolder>
|
| | | @REM
|
| | | @REM --------------------------------------------------------------------------
|
| | | @if [%1]==[] goto help
|
| | |
|
| | | @if [%2]==[] goto help
|
| | |
|
| | | @java -cp gitblit.jar;"%CD%\ext\*" 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
|
| | |
|
| | | :end |
| | |
| | | </env-entry>
|
| | |
|
| | | <!-- Gitblit Displayname -->
|
| | | <display-name>
|
| | | Gitblit - @gb.version@
|
| | | </display-name>
|
| | | <display-name>Gitblit - @gb.version@</display-name>
|
| | |
|
| | | <!-- PARAMS --> |
| | | |
| | |
|
| | | <!-- Gitblit Context Listener --><!-- STRIP
|
| | | <listener>
|
| | |
| | | </servlet-mapping>
|
| | |
|
| | |
|
| | | <!-- Raw Servlet
|
| | | <url-pattern> MUST match: |
| | | * RawFilter
|
| | | * com.gitblit.Constants.RAW_PATH
|
| | | * Wicket Filter ignorePaths parameter -->
|
| | | <servlet>
|
| | | <servlet-name>RawServlet</servlet-name>
|
| | | <servlet-class>com.gitblit.servlet.RawServlet</servlet-class>
|
| | | </servlet>
|
| | | <servlet-mapping>
|
| | | <servlet-name>RawServlet</servlet-name> |
| | | <url-pattern>/raw/*</url-pattern>
|
| | | </servlet-mapping> |
| | |
|
| | |
|
| | | <!-- Pages Servlet
|
| | | <url-pattern> MUST match:
|
| | | * PagesFilter
|
| | |
| | | <url-pattern>/robots.txt</url-pattern>
|
| | | </servlet-mapping>
|
| | |
|
| | | <filter>
|
| | | <filter-name>ProxyFilter</filter-name>
|
| | | <filter-class>com.gitblit.servlet.ProxyFilter</filter-class>
|
| | | </filter>
|
| | | <filter-mapping>
|
| | | <filter-name>ProxyFilter</filter-name>
|
| | | <url-pattern>/*</url-pattern>
|
| | | </filter-mapping>
|
| | | |
| | | <!-- Git Access Restriction Filter
|
| | | <url-pattern> MUST match:
|
| | | * GitServlet
|
| | |
| | | </filter-mapping>
|
| | |
|
| | |
|
| | | <!-- Pges Restriction Filter
|
| | | <!-- Branch Restriction Filter
|
| | | <url-pattern> MUST match: |
| | | * RawServlet
|
| | | * com.gitblit.Constants.BRANCH_PATH
|
| | | * Wicket Filter ignorePaths parameter -->
|
| | | <filter>
|
| | | <filter-name>RawFilter</filter-name>
|
| | | <filter-class>com.gitblit.servlet.RawFilter</filter-class>
|
| | | </filter>
|
| | | <filter-mapping>
|
| | | <filter-name>RawFilter</filter-name>
|
| | | <url-pattern>/raw/*</url-pattern>
|
| | | </filter-mapping>
|
| | | |
| | |
|
| | | <!-- Pages Restriction Filter
|
| | | <url-pattern> MUST match:
|
| | | * PagesServlet
|
| | | * com.gitblit.Constants.PAGES_PATH
|
| | |
| | | * FederationServlet <url-pattern>
|
| | | * RpcFilter <url-pattern>
|
| | | * RpcServlet <url-pattern>
|
| | | * RawFilter <url-pattern>
|
| | | * RawServlet <url-pattern>
|
| | | * PagesFilter <url-pattern>
|
| | | * PagesServlet <url-pattern>
|
| | | * com.gitblit.Constants.PAGES_PATH -->
|
| | | <param-value>r/,git/,pt,feed/,zip/,federation/,rpc/,pages/,robots.txt,logo.png,graph/,sparkleshare/</param-value>
|
| | | <param-value>r/,git/,pt,feed/,zip/,federation/,rpc/,raw/,pages/,robots.txt,logo.png,graph/,sparkleshare/</param-value>
|
| | | </init-param>
|
| | | </filter>
|
| | | <filter-mapping>
|
| | |
| | | <url-pattern>/*</url-pattern>
|
| | | </filter-mapping>
|
| | |
|
| | | </web-app>
|
| | | </web-app> |
| | |
| | | import java.util.Collections;
|
| | | import java.util.HashSet;
|
| | | import java.util.List;
|
| | | import java.util.Locale;
|
| | | import java.util.Map;
|
| | | import java.util.Set;
|
| | | import java.util.concurrent.ConcurrentHashMap;
|
| | |
| | |
|
| | | import com.gitblit.Constants.AccessPermission;
|
| | | import com.gitblit.Constants.AccountType;
|
| | | import com.gitblit.Constants.Transport;
|
| | | import com.gitblit.manager.IRuntimeManager;
|
| | | import com.gitblit.models.TeamModel;
|
| | | import com.gitblit.models.UserModel;
|
| | |
| | | private static final String STARRED = "starred";
|
| | |
|
| | | private static final String LOCALE = "locale";
|
| | |
|
| | | private static final String EMAILONMYTICKETCHANGES = "emailMeOnMyTicketChanges";
|
| | |
|
| | | private static final String TRANSPORT = "transport";
|
| | |
|
| | | private static final String ACCOUNTTYPE = "accountType";
|
| | |
|
| | |
| | | config.setBoolean(USER, model.username, DISABLED, true);
|
| | | }
|
| | | if (model.getPreferences() != null) {
|
| | | if (!StringUtils.isEmpty(model.getPreferences().locale)) {
|
| | | config.setString(USER, model.username, LOCALE, model.getPreferences().locale);
|
| | | Locale locale = model.getPreferences().getLocale();
|
| | | if (locale != null) {
|
| | | String val;
|
| | | if (StringUtils.isEmpty(locale.getCountry())) {
|
| | | val = locale.getLanguage();
|
| | | } else {
|
| | | val = locale.getLanguage() + "_" + locale.getCountry();
|
| | | }
|
| | | config.setString(USER, model.username, LOCALE, val);
|
| | | }
|
| | |
|
| | | config.setBoolean(USER, model.username, EMAILONMYTICKETCHANGES, model.getPreferences().isEmailMeOnMyTicketChanges());
|
| | |
|
| | | if (model.getPreferences().getTransport() != null) {
|
| | | config.setString(USER, model.username, TRANSPORT, model.getPreferences().getTransport().name());
|
| | | }
|
| | | }
|
| | |
|
| | |
| | | user.stateProvince = config.getString(USER, username, STATEPROVINCE);
|
| | | user.countryCode = config.getString(USER, username, COUNTRYCODE);
|
| | | user.cookie = config.getString(USER, username, COOKIE);
|
| | | user.getPreferences().locale = config.getString(USER, username, LOCALE);
|
| | | if (StringUtils.isEmpty(user.cookie) && !StringUtils.isEmpty(user.password)) {
|
| | | user.cookie = StringUtils.getSHA1(user.username + user.password);
|
| | | }
|
| | |
|
| | | // preferences
|
| | | user.getPreferences().setLocale(config.getString(USER, username, LOCALE));
|
| | | user.getPreferences().setEmailMeOnMyTicketChanges(config.getBoolean(USER, username, EMAILONMYTICKETCHANGES, true));
|
| | | user.getPreferences().setTransport(Transport.fromString(config.getString(USER, username, TRANSPORT)));
|
| | |
|
| | | // user roles
|
| | | Set<String> roles = new HashSet<String>(Arrays.asList(config.getStringList(
|
| | | USER, username, ROLE)));
|
| | |
| | |
|
| | | public static final String SPARKLESHARE_INVITE_PATH = "/sparkleshare/";
|
| | |
|
| | | public static final String RAW_PATH = "/raw/";
|
| | |
|
| | | public static final String BRANCH_GRAPH_PATH = "/graph/";
|
| | |
|
| | | public static final String BORDER = "*****************************************************************";
|
| | |
| | | public static final String R_TICKET = "refs/heads/ticket/";
|
| | |
|
| | | public static final String R_TICKETS_PATCHSETS = "refs/tickets/";
|
| | |
|
| | | public static final String R_MASTER = "refs/heads/master";
|
| | |
|
| | | public static final String MASTER = "master";
|
| | |
|
| | | public static final String R_DEVELOP = "refs/heads/develop";
|
| | |
|
| | | public static final String DEVELOP = "develop";
|
| | |
|
| | | public static String getVersion() {
|
| | | String v = Constants.class.getPackage().getImplementationVersion();
|
| | |
| | | * a client.
|
| | | */
|
| | | public static enum RpcRequest {
|
| | | // Order is important here. anything above LIST_SETTINGS requires
|
| | | // Order is important here. anything after LIST_SETTINGS requires
|
| | | // administrator privileges and web.allowRpcManagement.
|
| | | CLEAR_REPOSITORY_CACHE, REINDEX_TICKETS, GET_PROTOCOL, LIST_REPOSITORIES, LIST_BRANCHES, GET_USER, LIST_SETTINGS,
|
| | | CLEAR_REPOSITORY_CACHE, REINDEX_TICKETS, GET_PROTOCOL, LIST_REPOSITORIES, LIST_BRANCHES, GET_USER,
|
| | | FORK_REPOSITORY, LIST_SETTINGS,
|
| | | CREATE_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY,
|
| | | LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER,
|
| | | LIST_TEAMS, CREATE_TEAM, EDIT_TEAM, DELETE_TEAM,
|
| | |
| | | }
|
| | |
|
| | | /**
|
| | | * Enumeration of the feed content object types.
|
| | | */
|
| | | public static enum FeedObjectType {
|
| | | COMMIT, TAG;
|
| | |
|
| | | public static FeedObjectType forName(String name) {
|
| | | for (FeedObjectType type : values()) {
|
| | | if (type.name().equalsIgnoreCase(name)) {
|
| | | return type;
|
| | | }
|
| | | }
|
| | | return COMMIT;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String toString() {
|
| | | return name().toLowerCase();
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * The types of objects that can be indexed and queried.
|
| | | */
|
| | | public static enum SearchObjectType {
|
| | |
| | | return new NotificationManager(settings); |
| | | } |
| | | |
| | | @Provides @Singleton IUserManager provideUserManager(IRuntimeManager runtimeManager) { |
| | | return new UserManager(runtimeManager); |
| | | @Provides @Singleton IUserManager provideUserManager( |
| | | IRuntimeManager runtimeManager, |
| | | IPluginManager pluginManager) { |
| | | |
| | | return new UserManager(runtimeManager, pluginManager); |
| | | } |
| | | |
| | | @Provides @Singleton IAuthenticationManager provideAuthenticationManager( |
| | |
| | | |
| | | @Provides @Singleton IRepositoryManager provideRepositoryManager( |
| | | IRuntimeManager runtimeManager, |
| | | IPluginManager pluginManager, |
| | | IUserManager userManager) { |
| | | |
| | | return new RepositoryManager( |
| | | runtimeManager, |
| | | pluginManager, |
| | | userManager); |
| | | } |
| | | |
| | |
| | | // configure the Gitblit singleton for minimal, non-server operation
|
| | | RuntimeManager runtime = new RuntimeManager(settings, baseFolder).start();
|
| | | NoopNotificationManager notifications = new NoopNotificationManager().start();
|
| | | UserManager users = new UserManager(runtime).start();
|
| | | RepositoryManager repositories = new RepositoryManager(runtime, users).start();
|
| | | UserManager users = new UserManager(runtime, null).start();
|
| | | RepositoryManager repositories = new RepositoryManager(runtime, null, users).start();
|
| | | FederationManager federation = new FederationManager(runtime, notifications, repositories).start();
|
| | | IGitblit gitblit = new GitblitManager(runtime, null, notifications, users, null, null, repositories, null, federation);
|
| | |
|
| | |
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean isSendingMail() {
|
| | | return false;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void sendMailToAdministrators(String subject, String message) {
|
| | | }
|
| | |
|
| | |
| | | import java.util.Collections; |
| | | import java.util.Comparator; |
| | | import java.util.HashSet; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | |
| | | @Override |
| | | public boolean isServingRepositories() { |
| | | return servicesManager.isServingRepositories(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isServingHTTP() { |
| | | return servicesManager.isServingHTTP(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isServingGIT() { |
| | | return servicesManager.isServingGIT(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isServingSSH() { |
| | | return servicesManager.isServingSSH(); |
| | | } |
| | | |
| | | protected Object [] getModules() { |
| | |
| | | } |
| | | }); |
| | | |
| | | // consider the user's transport preference |
| | | RepositoryUrl preferredUrl = null; |
| | | Transport preferredTransport = user.getPreferences().getTransport(); |
| | | if (preferredTransport != null) { |
| | | Iterator<RepositoryUrl> itr = list.iterator(); |
| | | while (itr.hasNext()) { |
| | | RepositoryUrl url = itr.next(); |
| | | if (url.transport.equals(preferredTransport)) { |
| | | itr.remove(); |
| | | preferredUrl = url; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | if (preferredUrl != null) { |
| | | list.add(0, preferredUrl); |
| | | } |
| | | |
| | | return list; |
| | | } |
| | | |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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; |
| | | |
| | | import java.io.File; |
| | | import java.text.MessageFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | import org.kohsuke.args4j.Argument; |
| | | import org.kohsuke.args4j.CmdLineException; |
| | | import org.kohsuke.args4j.CmdLineParser; |
| | | import org.kohsuke.args4j.Option; |
| | | |
| | | import com.gitblit.manager.IRepositoryManager; |
| | | import com.gitblit.manager.IRuntimeManager; |
| | | import com.gitblit.manager.RepositoryManager; |
| | | import com.gitblit.manager.RuntimeManager; |
| | | import com.gitblit.models.RepositoryModel; |
| | | import com.gitblit.models.TicketModel; |
| | | import com.gitblit.models.TicketModel.Change; |
| | | import com.gitblit.tickets.BranchTicketService; |
| | | import com.gitblit.tickets.FileTicketService; |
| | | import com.gitblit.tickets.ITicketService; |
| | | import com.gitblit.tickets.RedisTicketService; |
| | | import com.gitblit.utils.StringUtils; |
| | | |
| | | /** |
| | | * A command-line tool to move all tickets from one ticket service to another. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public class MigrateTickets { |
| | | |
| | | public static void main(String... args) { |
| | | MigrateTickets migrate = new MigrateTickets(); |
| | | |
| | | // filter out the baseFolder parameter |
| | | List<String> filtered = new ArrayList<String>(); |
| | | String folder = "data"; |
| | | for (int i = 0; i < args.length; i++) { |
| | | String arg = args[i]; |
| | | if (arg.equals("--baseFolder")) { |
| | | if (i + 1 == args.length) { |
| | | System.out.println("Invalid --baseFolder parameter!"); |
| | | System.exit(-1); |
| | | } else if (!".".equals(args[i + 1])) { |
| | | folder = args[i + 1]; |
| | | } |
| | | i = i + 1; |
| | | } else { |
| | | filtered.add(arg); |
| | | } |
| | | } |
| | | |
| | | Params.baseFolder = folder; |
| | | Params params = new Params(); |
| | | CmdLineParser parser = new CmdLineParser(params); |
| | | try { |
| | | parser.parseArgument(filtered); |
| | | if (params.help) { |
| | | migrate.usage(parser, null); |
| | | return; |
| | | } |
| | | } catch (CmdLineException t) { |
| | | migrate.usage(parser, t); |
| | | return; |
| | | } |
| | | |
| | | // load the settings |
| | | FileSettings settings = params.FILESETTINGS; |
| | | if (!StringUtils.isEmpty(params.settingsfile)) { |
| | | if (new File(params.settingsfile).exists()) { |
| | | settings = new FileSettings(params.settingsfile); |
| | | } |
| | | } |
| | | |
| | | // migrate tickets |
| | | migrate.migrate(new File(Params.baseFolder), settings, params.outputServiceName); |
| | | System.exit(0); |
| | | } |
| | | |
| | | /** |
| | | * Display the command line usage of MigrateTickets. |
| | | * |
| | | * @param parser |
| | | * @param t |
| | | */ |
| | | protected final void usage(CmdLineParser parser, CmdLineException t) { |
| | | System.out.println(Constants.BORDER); |
| | | System.out.println(Constants.getGitBlitVersion()); |
| | | System.out.println(Constants.BORDER); |
| | | System.out.println(); |
| | | if (t != null) { |
| | | System.out.println(t.getMessage()); |
| | | System.out.println(); |
| | | } |
| | | if (parser != null) { |
| | | parser.printUsage(System.out); |
| | | System.out |
| | | .println("\nExample:\n java -gitblit.jar com.gitblit.MigrateTickets com.gitblit.tickets.RedisTicketService --baseFolder c:\\gitblit-data"); |
| | | } |
| | | System.exit(0); |
| | | } |
| | | |
| | | /** |
| | | * Migrate all tickets |
| | | * |
| | | * @param baseFolder |
| | | * @param settings |
| | | * @param outputServiceName |
| | | */ |
| | | protected void migrate(File baseFolder, IStoredSettings settings, String outputServiceName) { |
| | | // disable some services |
| | | settings.overrideSetting(Keys.web.allowLuceneIndexing, false); |
| | | settings.overrideSetting(Keys.git.enableGarbageCollection, false); |
| | | settings.overrideSetting(Keys.git.enableMirroring, false); |
| | | settings.overrideSetting(Keys.web.activityCacheDays, 0); |
| | | settings.overrideSetting(ITicketService.SETTING_UPDATE_DIFFSTATS, false); |
| | | |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings, baseFolder).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, null, null).start(); |
| | | |
| | | String inputServiceName = settings.getString(Keys.tickets.service, BranchTicketService.class.getSimpleName()); |
| | | if (StringUtils.isEmpty(inputServiceName)) { |
| | | System.err.println(MessageFormat.format("Please define a ticket service in \"{0}\"", Keys.tickets.service)); |
| | | System.exit(1); |
| | | } |
| | | |
| | | ITicketService inputService = null; |
| | | ITicketService outputService = null; |
| | | try { |
| | | inputService = getService(inputServiceName, runtimeManager, repositoryManager); |
| | | outputService = getService(outputServiceName, runtimeManager, repositoryManager); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | System.exit(1); |
| | | } |
| | | |
| | | if (!inputService.isReady()) { |
| | | System.err.println(String.format("%s INPUT service is not ready, check config.", inputService.getClass().getSimpleName())); |
| | | System.exit(1); |
| | | } |
| | | |
| | | if (!outputService.isReady()) { |
| | | System.err.println(String.format("%s OUTPUT service is not ready, check config.", outputService.getClass().getSimpleName())); |
| | | System.exit(1); |
| | | } |
| | | |
| | | // migrate tickets |
| | | long start = System.nanoTime(); |
| | | long totalTickets = 0; |
| | | long totalChanges = 0; |
| | | for (RepositoryModel repository : repositoryManager.getRepositoryModels(null)) { |
| | | Set<Long> ids = inputService.getIds(repository); |
| | | if (ids == null || ids.isEmpty()) { |
| | | // nothing to migrate |
| | | continue; |
| | | } |
| | | |
| | | // delete any tickets we may have in the output ticket service |
| | | outputService.deleteAll(repository); |
| | | |
| | | for (long id : ids) { |
| | | List<Change> journal = inputService.getJournal(repository, id); |
| | | if (journal == null || journal.size() == 0) { |
| | | continue; |
| | | } |
| | | TicketModel ticket = outputService.createTicket(repository, id, journal.get(0)); |
| | | if (ticket == null) { |
| | | System.err.println(String.format("Failed to migrate %s #%s", repository.name, id)); |
| | | System.exit(1); |
| | | } |
| | | totalTickets++; |
| | | System.out.println(String.format("%s #%s: %s", repository.name, ticket.number, ticket.title)); |
| | | for (int i = 1; i < journal.size(); i++) { |
| | | TicketModel updated = outputService.updateTicket(repository, ticket.number, journal.get(i)); |
| | | if (updated != null) { |
| | | System.out.println(String.format(" applied change %d", i)); |
| | | totalChanges++; |
| | | } else { |
| | | System.err.println(String.format("Failed to apply change %d:\n%s", i, journal.get(i))); |
| | | System.exit(1); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | inputService.stop(); |
| | | outputService.stop(); |
| | | |
| | | repositoryManager.stop(); |
| | | runtimeManager.stop(); |
| | | |
| | | long end = System.nanoTime(); |
| | | |
| | | System.out.println(String.format("Migrated %d tickets composed of %d journal entries in %d seconds", |
| | | totalTickets, totalTickets + totalChanges, TimeUnit.NANOSECONDS.toSeconds(end - start))); |
| | | } |
| | | |
| | | protected ITicketService getService(String serviceName, IRuntimeManager runtimeManager, IRepositoryManager repositoryManager) throws Exception { |
| | | ITicketService service = null; |
| | | Class<?> serviceClass = Class.forName(serviceName); |
| | | if (RedisTicketService.class.isAssignableFrom(serviceClass)) { |
| | | // Redis ticket service |
| | | service = new RedisTicketService(runtimeManager, null, null, null, repositoryManager).start(); |
| | | } else if (BranchTicketService.class.isAssignableFrom(serviceClass)) { |
| | | // Branch ticket service |
| | | service = new BranchTicketService(runtimeManager, null, null, null, repositoryManager).start(); |
| | | } else if (FileTicketService.class.isAssignableFrom(serviceClass)) { |
| | | // File ticket service |
| | | service = new FileTicketService(runtimeManager, null, null, null, repositoryManager).start(); |
| | | } else { |
| | | System.err.println("Unknown ticket service " + serviceName); |
| | | } |
| | | return service; |
| | | } |
| | | |
| | | /** |
| | | * Parameters. |
| | | */ |
| | | public static class Params { |
| | | |
| | | public static String baseFolder; |
| | | |
| | | @Option(name = "--help", aliases = { "-h"}, usage = "Show this help") |
| | | public Boolean help = false; |
| | | |
| | | private final FileSettings FILESETTINGS = new FileSettings(new File(baseFolder, Constants.PROPERTIES_FILE).getAbsolutePath()); |
| | | |
| | | @Option(name = "--repositoriesFolder", usage = "Git Repositories Folder", metaVar = "PATH") |
| | | public String repositoriesFolder = FILESETTINGS.getString(Keys.git.repositoriesFolder, "git"); |
| | | |
| | | @Option(name = "--settings", usage = "Path to alternative settings", metaVar = "FILE") |
| | | public String settingsfile; |
| | | |
| | | @Argument(index = 0, required = true, metaVar = "OUTPUTSERVICE", usage = "The destination/output ticket service") |
| | | public String outputServiceName; |
| | | } |
| | | } |
| | |
| | | settings.overrideSetting(Keys.web.activityCacheDays, 0); |
| | | |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings, baseFolder).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, null).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, null, null).start(); |
| | | |
| | | String serviceName = settings.getString(Keys.tickets.service, BranchTicketService.class.getSimpleName()); |
| | | if (StringUtils.isEmpty(serviceName)) { |
| | |
| | |
|
| | | // create list of available scripts by excluding inherited scripts
|
| | | List<String> scripts = new ArrayList<String>();
|
| | | for (String script : settings.pushScripts) {
|
| | | if (!inherited.contains(script)) {
|
| | | scripts.add(script);
|
| | | if (!ArrayUtils.isEmpty(settings.pushScripts)) {
|
| | | for (String script : settings.pushScripts) {
|
| | | if (!inherited.contains(script)) {
|
| | | scripts.add(script);
|
| | | }
|
| | | }
|
| | | }
|
| | | return scripts;
|
| | |
| | | public final void init(FilterConfig filterConfig) throws ServletException {
|
| | | ServletContext context = filterConfig.getServletContext();
|
| | | ObjectGraph objectGraph = (ObjectGraph) context.getAttribute(DaggerContext.INJECTOR_NAME);
|
| | | inject(objectGraph);
|
| | | inject(objectGraph, filterConfig);
|
| | | }
|
| | |
|
| | | protected abstract void inject(ObjectGraph dagger);
|
| | | protected abstract void inject(ObjectGraph dagger, FilterConfig filterConfig) throws ServletException;
|
| | |
|
| | | @Override
|
| | | public void destroy() {
|
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.extensions; |
| | | |
| | | import org.apache.wicket.Application; |
| | | import org.apache.wicket.IInitializer; |
| | | |
| | | import ro.fortsoft.pf4j.PluginWrapper; |
| | | |
| | | import com.gitblit.wicket.GitblitWicketApp; |
| | | |
| | | /** |
| | | * A Gitblit plugin that is allowed to extend the Wicket webapp. |
| | | * |
| | | * @author James Moger |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract class GitblitWicketPlugin extends GitblitPlugin implements IInitializer { |
| | | |
| | | public GitblitWicketPlugin(PluginWrapper wrapper) { |
| | | super(wrapper); |
| | | } |
| | | |
| | | @Override |
| | | public final void init(Application application) { |
| | | init((GitblitWicketApp) application); |
| | | } |
| | | |
| | | /** |
| | | * Allows plugins to extend the web application. |
| | | * |
| | | * @param app |
| | | * @since 1.6.0 |
| | | */ |
| | | protected abstract void init(GitblitWicketApp app); |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.extensions; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | import javax.servlet.Filter; |
| | | import javax.servlet.FilterChain; |
| | | import javax.servlet.FilterConfig; |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.ServletRequest; |
| | | import javax.servlet.ServletResponse; |
| | | |
| | | import ro.fortsoft.pf4j.ExtensionPoint; |
| | | |
| | | /** |
| | | * Extension point to intercept HTTP requests passing through the server. |
| | | * |
| | | * @author David Ostrovsky |
| | | * @since 1.6.0 |
| | | * |
| | | */ |
| | | public abstract class HttpRequestFilter implements Filter, ExtensionPoint { |
| | | |
| | | @Override |
| | | public void init(FilterConfig config) throws ServletException { |
| | | } |
| | | |
| | | @Override |
| | | public void destroy() { |
| | | } |
| | | |
| | | @Override |
| | | public abstract void doFilter(ServletRequest request, ServletResponse response, |
| | | FilterChain chain) throws IOException, ServletException; |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.extensions; |
| | | |
| | | import ro.fortsoft.pf4j.ExtensionPoint; |
| | | |
| | | /** |
| | | * Extension point to allow plugins to listen to major Gitblit lifecycle events. |
| | | * |
| | | * @author James Moger |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract class LifeCycleListener implements ExtensionPoint { |
| | | |
| | | /** |
| | | * Called after all internal managers have been started. |
| | | * This may be useful for reporting "server is ready" to a monitoring system. |
| | | * |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract void onStartup(); |
| | | |
| | | /** |
| | | * Called when the servlet container is gracefully shutting-down the webapp. |
| | | * This is called before the internal managers are stopped. |
| | | * |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract void onShutdown(); |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.extensions; |
| | | |
| | | import java.util.List; |
| | | |
| | | import ro.fortsoft.pf4j.ExtensionPoint; |
| | | |
| | | import com.gitblit.models.NavLink; |
| | | import com.gitblit.models.UserModel; |
| | | |
| | | /** |
| | | * Extension point to contribute top-level navigation links. |
| | | * |
| | | * @author James Moger |
| | | * @since 1.6.0 |
| | | * |
| | | */ |
| | | public abstract class NavLinkExtension implements ExtensionPoint { |
| | | |
| | | /** |
| | | * @param user |
| | | * @since 1.6.0 |
| | | * @return a list of nav links |
| | | */ |
| | | public abstract List<NavLink> getNavLinks(UserModel user); |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.extensions; |
| | | |
| | | import ro.fortsoft.pf4j.ExtensionPoint; |
| | | |
| | | import com.gitblit.models.RepositoryModel; |
| | | |
| | | /** |
| | | * Extension point to allow plugins to listen to major repository lifecycle events. |
| | | * |
| | | * @author James Moger |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract class RepositoryLifeCycleListener implements ExtensionPoint { |
| | | |
| | | /** |
| | | * Called after a repository has been created. |
| | | * |
| | | * @param repository |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract void onCreation(RepositoryModel repository); |
| | | |
| | | /** |
| | | * Called after a repository has been deleted. |
| | | * |
| | | * @param repository |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract void onDeletion(RepositoryModel repository); |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.extensions; |
| | | |
| | | import java.util.List; |
| | | |
| | | import ro.fortsoft.pf4j.ExtensionPoint; |
| | | |
| | | import com.gitblit.models.NavLink; |
| | | import com.gitblit.models.RepositoryModel; |
| | | import com.gitblit.models.UserModel; |
| | | |
| | | /** |
| | | * Extension point to contribute repository page navigation links. |
| | | * |
| | | * @author James Moger |
| | | * @since 1.6.0 |
| | | * |
| | | */ |
| | | public abstract class RepositoryNavLinkExtension implements ExtensionPoint { |
| | | |
| | | /** |
| | | * @param user |
| | | * @param repository |
| | | * @since 1.6.0 |
| | | * @return a list of nav links |
| | | */ |
| | | public abstract List<NavLink> getNavLinks(UserModel user, RepositoryModel repository); |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.extensions; |
| | | |
| | | import java.util.List; |
| | | |
| | | import ro.fortsoft.pf4j.ExtensionPoint; |
| | | |
| | | import com.gitblit.models.Menu.MenuItem; |
| | | import com.gitblit.models.UserModel; |
| | | |
| | | /** |
| | | * Extension point to contribute user menu items. |
| | | * |
| | | * @author James Moger |
| | | * @since 1.6.0 |
| | | * |
| | | */ |
| | | public abstract class UserMenuExtension implements ExtensionPoint { |
| | | |
| | | /** |
| | | * @param user |
| | | * @since 1.6.0 |
| | | * @return a list of menu items |
| | | */ |
| | | public abstract List<MenuItem> getMenuItems(UserModel user); |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.extensions; |
| | | |
| | | import ro.fortsoft.pf4j.ExtensionPoint; |
| | | |
| | | import com.gitblit.models.TeamModel; |
| | | import com.gitblit.models.UserModel; |
| | | |
| | | /** |
| | | * Extension point to allow plugins to listen to major user and team lifecycle events. |
| | | * |
| | | * @author James Moger |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract class UserTeamLifeCycleListener implements ExtensionPoint { |
| | | |
| | | /** |
| | | * Called after a user has been created. |
| | | * |
| | | * @param user |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract void onCreation(UserModel user); |
| | | |
| | | /** |
| | | * Called after a user has been deleted. |
| | | * |
| | | * @param user |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract void onDeletion(UserModel user); |
| | | |
| | | /** |
| | | * Called after a team has been created. |
| | | * |
| | | * @param team |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract void onCreation(TeamModel team); |
| | | |
| | | /** |
| | | * Called after a team has been deleted. |
| | | * |
| | | * @param team |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract void onDeletion(TeamModel team); |
| | | } |
| | |
| | | return;
|
| | | }
|
| | |
|
| | | logRefChange(commands);
|
| | | updateIncrementalPushTags(commands);
|
| | | updateGitblitRefLog(commands);
|
| | |
|
| | | // check for updates pushed to the BranchTicketService branch
|
| | | // if the BranchTicketService is active it will reindex, as appropriate
|
| | | for (ReceiveCommand cmd : commands) {
|
| | | if (Result.OK.equals(cmd.getResult())
|
| | | && BranchTicketService.BRANCH.equals(cmd.getRefName())) {
|
| | | rp.getRepository().fireEvent(new ReceiveCommandEvent(repository, cmd));
|
| | | }
|
| | | }
|
| | |
|
| | | // call post-receive plugins
|
| | | for (ReceiveHook hook : gitblit.getExtensions(ReceiveHook.class)) {
|
| | | try {
|
| | | hook.onPostReceive(this, commands);
|
| | | } catch (Exception e) {
|
| | | LOGGER.error("Failed to execute extension", e);
|
| | | }
|
| | | }
|
| | |
|
| | | // run Groovy hook scripts
|
| | | Set<String> scripts = new LinkedHashSet<String>();
|
| | | scripts.addAll(gitblit.getPostReceiveScriptsInherited(repository));
|
| | | if (!ArrayUtils.isEmpty(repository.postReceiveScripts)) {
|
| | | scripts.addAll(repository.postReceiveScripts);
|
| | | }
|
| | | runGroovy(commands, scripts);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Log the ref changes in the container log.
|
| | | *
|
| | | * @param commands
|
| | | */
|
| | | protected void logRefChange(Collection<ReceiveCommand> commands) {
|
| | | boolean isRefCreationOrDeletion = false;
|
| | |
|
| | | // log ref changes
|
| | |
| | | if (isRefCreationOrDeletion) {
|
| | | gitblit.resetRepositoryCache(repository.name);
|
| | | }
|
| | | }
|
| | |
|
| | | if (repository.useIncrementalPushTags) {
|
| | | // tag each pushed branch tip
|
| | | String emailAddress = user.emailAddress == null ? rp.getRefLogIdent().getEmailAddress() : user.emailAddress;
|
| | | PersonIdent userIdent = new PersonIdent(user.getDisplayName(), emailAddress);
|
| | |
|
| | | for (ReceiveCommand cmd : commands) {
|
| | | if (!cmd.getRefName().startsWith(Constants.R_HEADS)) {
|
| | | // only tag branch ref changes
|
| | | continue;
|
| | | }
|
| | |
|
| | | if (!ReceiveCommand.Type.DELETE.equals(cmd.getType())
|
| | | && ReceiveCommand.Result.OK.equals(cmd.getResult())) {
|
| | | String objectId = cmd.getNewId().getName();
|
| | | String branch = cmd.getRefName().substring(Constants.R_HEADS.length());
|
| | | // get translation based on the server's locale setting
|
| | | String template = Translation.get("gb.incrementalPushTagMessage");
|
| | | String msg = MessageFormat.format(template, branch);
|
| | | String prefix;
|
| | | if (StringUtils.isEmpty(repository.incrementalPushTagPrefix)) {
|
| | | prefix = settings.getString(Keys.git.defaultIncrementalPushTagPrefix, "r");
|
| | | } else {
|
| | | prefix = repository.incrementalPushTagPrefix;
|
| | | }
|
| | |
|
| | | JGitUtils.createIncrementalRevisionTag(
|
| | | rp.getRepository(),
|
| | | objectId,
|
| | | userIdent,
|
| | | prefix,
|
| | | "0",
|
| | | msg);
|
| | | }
|
| | | }
|
| | | /**
|
| | | * Optionally update the incremental push tags.
|
| | | *
|
| | | * @param commands
|
| | | */
|
| | | protected void updateIncrementalPushTags(Collection<ReceiveCommand> commands) {
|
| | | if (!repository.useIncrementalPushTags) {
|
| | | return;
|
| | | }
|
| | |
|
| | | // update push log
|
| | | try {
|
| | | RefLogUtils.updateRefLog(user, rp.getRepository(), commands);
|
| | | LOGGER.debug(MessageFormat.format("{0} push log updated", repository.name));
|
| | | } catch (Exception e) {
|
| | | LOGGER.error(MessageFormat.format("Failed to update {0} pushlog", repository.name), e);
|
| | | }
|
| | | // tag each pushed branch tip
|
| | | String emailAddress = user.emailAddress == null ? getRefLogIdent().getEmailAddress() : user.emailAddress;
|
| | | PersonIdent userIdent = new PersonIdent(user.getDisplayName(), emailAddress);
|
| | |
|
| | | // check for updates pushed to the BranchTicketService branch
|
| | | // if the BranchTicketService is active it will reindex, as appropriate
|
| | | for (ReceiveCommand cmd : commands) {
|
| | | if (Result.OK.equals(cmd.getResult())
|
| | | && BranchTicketService.BRANCH.equals(cmd.getRefName())) {
|
| | | rp.getRepository().fireEvent(new ReceiveCommandEvent(repository, cmd));
|
| | | if (!cmd.getRefName().startsWith(Constants.R_HEADS)) {
|
| | | // only tag branch ref changes
|
| | | continue;
|
| | | }
|
| | |
|
| | | if (!ReceiveCommand.Type.DELETE.equals(cmd.getType())
|
| | | && ReceiveCommand.Result.OK.equals(cmd.getResult())) {
|
| | | String objectId = cmd.getNewId().getName();
|
| | | String branch = cmd.getRefName().substring(Constants.R_HEADS.length());
|
| | | // get translation based on the server's locale setting
|
| | | String template = Translation.get("gb.incrementalPushTagMessage");
|
| | | String msg = MessageFormat.format(template, branch);
|
| | | String prefix;
|
| | | if (StringUtils.isEmpty(repository.incrementalPushTagPrefix)) {
|
| | | prefix = settings.getString(Keys.git.defaultIncrementalPushTagPrefix, "r");
|
| | | } else {
|
| | | prefix = repository.incrementalPushTagPrefix;
|
| | | }
|
| | |
|
| | | JGitUtils.createIncrementalRevisionTag(
|
| | | getRepository(),
|
| | | objectId,
|
| | | userIdent,
|
| | | prefix,
|
| | | "0",
|
| | | msg);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | // call post-receive plugins
|
| | | for (ReceiveHook hook : gitblit.getExtensions(ReceiveHook.class)) {
|
| | | try {
|
| | | hook.onPostReceive(this, commands);
|
| | | } catch (Exception e) {
|
| | | LOGGER.error("Failed to execute extension", e);
|
| | | }
|
| | | /**
|
| | | * Update Gitblit's internal reflog.
|
| | | *
|
| | | * @param commands
|
| | | */
|
| | | protected void updateGitblitRefLog(Collection<ReceiveCommand> commands) {
|
| | | try {
|
| | | RefLogUtils.updateRefLog(user, getRepository(), commands);
|
| | | LOGGER.debug(MessageFormat.format("{0} reflog updated", repository.name));
|
| | | } catch (Exception e) {
|
| | | LOGGER.error(MessageFormat.format("Failed to update {0} reflog", repository.name), e);
|
| | | }
|
| | |
|
| | | // run Groovy hook scripts
|
| | | Set<String> scripts = new LinkedHashSet<String>();
|
| | | scripts.addAll(gitblit.getPostReceiveScriptsInherited(repository));
|
| | | if (!ArrayUtils.isEmpty(repository.postReceiveScripts)) {
|
| | | scripts.addAll(repository.postReceiveScripts);
|
| | | }
|
| | | runGroovy(commands, scripts);
|
| | | }
|
| | |
|
| | | /** Execute commands to update references. */
|
| | |
| | | if (ticket != null) {
|
| | | ticketNotifier.queueMailing(ticket);
|
| | |
|
| | | // update the reflog with the merge
|
| | | if (oldRef != null) {
|
| | | ReceiveCommand cmd = new ReceiveCommand(oldRef.getObjectId(),
|
| | | ObjectId.fromString(mergeResult.sha), oldRef.getName());
|
| | | RefLogUtils.updateRefLog(user, getRepository(), Arrays.asList(cmd));
|
| | | cmd.setResult(Result.OK);
|
| | | List<ReceiveCommand> commands = Arrays.asList(cmd);
|
| | |
|
| | | logRefChange(commands);
|
| | | updateIncrementalPushTags(commands);
|
| | | updateGitblitRefLog(commands);
|
| | | }
|
| | |
|
| | | // call patchset hooks
|
| | |
| | | } |
| | | |
| | | @Override |
| | | public boolean isServingHTTP() { |
| | | return runtimeManager.isServingHTTP(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isServingGIT() { |
| | | return runtimeManager.isServingGIT(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isServingSSH() { |
| | | return runtimeManager.isServingSSH(); |
| | | } |
| | | |
| | | @Override |
| | | public TimeZone getTimezone() { |
| | | return runtimeManager.getTimezone(); |
| | | } |
| | |
| | | /* |
| | | * NOTIFICATION MANAGER |
| | | */ |
| | | |
| | | @Override |
| | | public boolean isSendingMail() { |
| | | return notificationManager.isSendingMail(); |
| | | } |
| | | |
| | | @Override |
| | | public void sendMailToAdministrators(String subject, String message) { |
| | |
| | | } |
| | | |
| | | @Override |
| | | public boolean canDelete(RepositoryModel model) { |
| | | return repositoryManager.canDelete(model); |
| | | } |
| | | |
| | | @Override |
| | | public boolean deleteRepositoryModel(RepositoryModel model) { |
| | | return repositoryManager.deleteRepositoryModel(model); |
| | | } |
| | |
| | | public interface INotificationManager extends IManager { |
| | | |
| | | /** |
| | | * Returns true if the email service is configured and ready to send notifications. |
| | | * |
| | | * @return true if the email service is operational |
| | | * @since 1.6.0 |
| | | */ |
| | | boolean isSendingMail(); |
| | | |
| | | /** |
| | | * Notify the administrators by email. |
| | | * |
| | | * @param subject |
| | |
| | | void updateConfiguration(Repository r, RepositoryModel repository); |
| | | |
| | | /** |
| | | * Returns true if the repository can be deleted. |
| | | * |
| | | * @param model |
| | | * @return true if the repository can be deleted |
| | | * @since 1.6.0 |
| | | */ |
| | | boolean canDelete(RepositoryModel model); |
| | | |
| | | /** |
| | | * Deletes the repository from the file system and removes the repository |
| | | * permission from all repository users. |
| | | * |
| | |
| | | boolean isServingRepositories(); |
| | | |
| | | /** |
| | | * Determine if this Gitblit instance is actively serving git repositories |
| | | * over HTTP. |
| | | * |
| | | * @return true if Gitblit is serving repositories over HTTP |
| | | * @since 1.6.0 |
| | | */ |
| | | boolean isServingHTTP(); |
| | | |
| | | /** |
| | | * Determine if this Gitblit instance is actively serving git repositories |
| | | * over the GIT Daemon protocol. |
| | | * |
| | | * @return true if Gitblit is serving repositories over the GIT Daemon protocol |
| | | * @since 1.6.0 |
| | | */ |
| | | boolean isServingGIT(); |
| | | |
| | | /** |
| | | * Determine if this Gitblit instance is actively serving git repositories |
| | | * over the SSH protocol. |
| | | * |
| | | * @return true if Gitblit is serving repositories over the SSH protocol |
| | | * @since 1.6.0 |
| | | */ |
| | | boolean isServingSSH(); |
| | | |
| | | /** |
| | | * Determine if this Gitblit instance is running in debug mode |
| | | * |
| | | * @return true if Gitblit is running in debug mode |
| | |
| | | return this; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isSendingMail() { |
| | | return mailService.isReady(); |
| | | } |
| | | |
| | | /** |
| | | * Notify the administrators by email. |
| | | * |
| | |
| | | import com.gitblit.GitBlitException; |
| | | import com.gitblit.IStoredSettings; |
| | | import com.gitblit.Keys; |
| | | import com.gitblit.extensions.RepositoryLifeCycleListener; |
| | | import com.gitblit.models.ForkModel; |
| | | import com.gitblit.models.Metric; |
| | | import com.gitblit.models.RefModel; |
| | |
| | | |
| | | private final IRuntimeManager runtimeManager; |
| | | |
| | | private final IPluginManager pluginManager; |
| | | |
| | | private final IUserManager userManager; |
| | | |
| | | private final File repositoriesFolder; |
| | |
| | | |
| | | public RepositoryManager( |
| | | IRuntimeManager runtimeManager, |
| | | IPluginManager pluginManager, |
| | | IUserManager userManager) { |
| | | |
| | | this.settings = runtimeManager.getSettings(); |
| | | this.runtimeManager = runtimeManager; |
| | | this.pluginManager = pluginManager; |
| | | this.userManager = userManager; |
| | | this.repositoriesFolder = runtimeManager.getFileOrFolder(Keys.git.repositoriesFolder, "${baseFolder}/git"); |
| | | } |
| | |
| | | removeFromCachedRepositoryList(repositoryName); |
| | | // model will actually be replaced on next load because config is stale |
| | | addToCachedRepositoryList(repository); |
| | | |
| | | if (isCreate && pluginManager != null) { |
| | | for (RepositoryLifeCycleListener listener : pluginManager.getExtensions(RepositoryLifeCycleListener.class)) { |
| | | try { |
| | | listener.onCreation(repository); |
| | | } catch (Throwable t) { |
| | | logger.error(String.format("failed to call plugin onCreation %s", repositoryName), t); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns true if the repository can be deleted. |
| | | * |
| | | * @return true if the repository can be deleted |
| | | */ |
| | | @Override |
| | | public boolean canDelete(RepositoryModel repository) { |
| | | return settings.getBoolean(Keys.web.allowDeletingNonEmptyRepositories, true) |
| | | || !repository.hasCommits; |
| | | } |
| | | |
| | | /** |
| | | * Deletes the repository from the file system and removes the repository |
| | | * permission from all repository users. |
| | | * |
| | |
| | | */ |
| | | @Override |
| | | public boolean deleteRepository(String repositoryName) { |
| | | RepositoryModel repository = getRepositoryModel(repositoryName); |
| | | if (!canDelete(repository)) { |
| | | logger.warn("Attempt to delete {} rejected!", repositoryName); |
| | | return false; |
| | | } |
| | | |
| | | try { |
| | | close(repositoryName); |
| | | // clear the repository cache |
| | |
| | | FileUtils.delete(folder, FileUtils.RECURSIVE | FileUtils.RETRY); |
| | | if (userManager.deleteRepositoryRole(repositoryName)) { |
| | | logger.info(MessageFormat.format("Repository \"{0}\" deleted", repositoryName)); |
| | | |
| | | if (pluginManager != null) { |
| | | for (RepositoryLifeCycleListener listener : pluginManager.getExtensions(RepositoryLifeCycleListener.class)) { |
| | | try { |
| | | listener.onDeletion(repository); |
| | | } catch (Throwable t) { |
| | | logger.error(String.format("failed to call plugin onDeletion %s", repositoryName), t); |
| | | } |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | } |
| | |
| | | */ |
| | | @Override |
| | | public boolean isServingRepositories() { |
| | | return settings.getBoolean(Keys.git.enableGitServlet, true) |
| | | || (settings.getInteger(Keys.git.daemonPort, 0) > 0) |
| | | || (settings.getInteger(Keys.git.sshPort, 0) > 0); |
| | | return isServingHTTP() |
| | | || isServingGIT() |
| | | || isServingSSH(); |
| | | } |
| | | |
| | | /** |
| | | * Determine if this Gitblit instance is actively serving git repositories |
| | | * over the HTTP protocol. |
| | | * |
| | | * @return true if Gitblit is serving repositories over the HTTP protocol |
| | | */ |
| | | @Override |
| | | public boolean isServingHTTP() { |
| | | return settings.getBoolean(Keys.git.enableGitServlet, true); |
| | | } |
| | | |
| | | /** |
| | | * Determine if this Gitblit instance is actively serving git repositories |
| | | * over the Git Daemon protocol. |
| | | * |
| | | * @return true if Gitblit is serving repositories over the Git Daemon protocol |
| | | */ |
| | | @Override |
| | | public boolean isServingGIT() { |
| | | return settings.getInteger(Keys.git.daemonPort, 0) > 0; |
| | | } |
| | | |
| | | /** |
| | | * Determine if this Gitblit instance is actively serving git repositories |
| | | * over the SSH protocol. |
| | | * |
| | | * @return true if Gitblit is serving repositories over the SSH protocol |
| | | */ |
| | | @Override |
| | | public boolean isServingSSH() { |
| | | return settings.getInteger(Keys.git.sshPort, 0) > 0; |
| | | } |
| | | |
| | | /** |
| | |
| | | public ServicesManager(IGitblit gitblit) { |
| | | this.settings = gitblit.getSettings(); |
| | | this.gitblit = gitblit; |
| | | int defaultThreadPoolSize = settings.getInteger(Keys.execution.defaultThreadPoolSize, 1); |
| | | this.idGenerator = new IdGenerator(); |
| | | this.workQueue = new WorkQueue(idGenerator, 1); |
| | | this.workQueue = new WorkQueue(idGenerator, defaultThreadPoolSize); |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | |
| | | public boolean isServingRepositories() { |
| | | return settings.getBoolean(Keys.git.enableGitServlet, true) |
| | | || (gitDaemon != null && gitDaemon.isRunning()) |
| | | || (sshDaemon != null && sshDaemon.isRunning()); |
| | | return isServingHTTP() |
| | | || isServingGIT() |
| | | || isServingSSH(); |
| | | } |
| | | |
| | | public boolean isServingHTTP() { |
| | | return settings.getBoolean(Keys.git.enableGitServlet, true); |
| | | } |
| | | |
| | | public boolean isServingGIT() { |
| | | return gitDaemon != null && gitDaemon.isRunning(); |
| | | } |
| | | |
| | | public boolean isServingSSH() { |
| | | return sshDaemon != null && sshDaemon.isRunning(); |
| | | } |
| | | |
| | | protected void configureFederation() { |
| | |
| | | import com.gitblit.IStoredSettings; |
| | | import com.gitblit.IUserService; |
| | | import com.gitblit.Keys; |
| | | import com.gitblit.extensions.UserTeamLifeCycleListener; |
| | | import com.gitblit.models.TeamModel; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.utils.StringUtils; |
| | |
| | | |
| | | private final IRuntimeManager runtimeManager; |
| | | |
| | | private final IPluginManager pluginManager; |
| | | |
| | | private final Map<String, String> legacyBackingServices; |
| | | |
| | | private IUserService userService; |
| | | |
| | | public UserManager(IRuntimeManager runtimeManager) { |
| | | public UserManager(IRuntimeManager runtimeManager, IPluginManager pluginManager) { |
| | | this.settings = runtimeManager.getSettings(); |
| | | this.runtimeManager = runtimeManager; |
| | | this.pluginManager = pluginManager; |
| | | |
| | | // map of legacy realm backing user services |
| | | legacyBackingServices = new HashMap<String, String>(); |
| | |
| | | */ |
| | | @Override |
| | | public boolean updateUserModel(UserModel model) { |
| | | return userService.updateUserModel(model); |
| | | final boolean isCreate = null == userService.getUserModel(model.username); |
| | | if (userService.updateUserModel(model)) { |
| | | if (isCreate) { |
| | | callCreateUserListeners(model); |
| | | } |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Override |
| | | public boolean updateUserModel(String username, UserModel model) { |
| | | return userService.updateUserModel(username, model); |
| | | final boolean isCreate = null == userService.getUserModel(username); |
| | | if (userService.updateUserModel(username, model)) { |
| | | if (isCreate) { |
| | | callCreateUserListeners(model); |
| | | } |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Override |
| | | public boolean deleteUserModel(UserModel model) { |
| | | return userService.deleteUserModel(model); |
| | | if (userService.deleteUserModel(model)) { |
| | | callDeleteUserListeners(model); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | return false; |
| | | } |
| | | String usernameDecoded = StringUtils.decodeUsername(username); |
| | | return userService.deleteUser(usernameDecoded); |
| | | UserModel user = getUserModel(usernameDecoded); |
| | | if (userService.deleteUser(usernameDecoded)) { |
| | | callDeleteUserListeners(user); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Override |
| | | public boolean updateTeamModel(TeamModel model) { |
| | | return userService.updateTeamModel(model); |
| | | final boolean isCreate = null == userService.getTeamModel(model.name); |
| | | if (userService.updateTeamModel(model)) { |
| | | if (isCreate) { |
| | | callCreateTeamListeners(model); |
| | | } |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Override |
| | | public boolean updateTeamModel(String teamname, TeamModel model) { |
| | | return userService.updateTeamModel(teamname, model); |
| | | final boolean isCreate = null == userService.getTeamModel(teamname); |
| | | if (userService.updateTeamModel(teamname, model)) { |
| | | if (isCreate) { |
| | | callCreateTeamListeners(model); |
| | | } |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Override |
| | | public boolean deleteTeamModel(TeamModel model) { |
| | | return userService.deleteTeamModel(model); |
| | | if (userService.deleteTeamModel(model)) { |
| | | callDeleteTeamListeners(model); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Override |
| | | public boolean deleteTeam(String teamname) { |
| | | return userService.deleteTeam(teamname); |
| | | TeamModel team = userService.getTeamModel(teamname); |
| | | if (userService.deleteTeam(teamname)) { |
| | | callDeleteTeamListeners(team); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | public boolean deleteRepositoryRole(String role) { |
| | | return userService.deleteRepositoryRole(role); |
| | | } |
| | | |
| | | protected void callCreateUserListeners(UserModel user) { |
| | | if (pluginManager == null || user == null) { |
| | | return; |
| | | } |
| | | |
| | | for (UserTeamLifeCycleListener listener : pluginManager.getExtensions(UserTeamLifeCycleListener.class)) { |
| | | try { |
| | | listener.onCreation(user); |
| | | } catch (Throwable t) { |
| | | logger.error(String.format("failed to call plugin.onCreation%s", user.username), t); |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected void callCreateTeamListeners(TeamModel team) { |
| | | if (pluginManager == null || team == null) { |
| | | return; |
| | | } |
| | | |
| | | for (UserTeamLifeCycleListener listener : pluginManager.getExtensions(UserTeamLifeCycleListener.class)) { |
| | | try { |
| | | listener.onCreation(team); |
| | | } catch (Throwable t) { |
| | | logger.error(String.format("failed to call plugin.onCreation %s", team.name), t); |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected void callDeleteUserListeners(UserModel user) { |
| | | if (pluginManager == null || user == null) { |
| | | return; |
| | | } |
| | | |
| | | for (UserTeamLifeCycleListener listener : pluginManager.getExtensions(UserTeamLifeCycleListener.class)) { |
| | | try { |
| | | listener.onDeletion(user); |
| | | } catch (Throwable t) { |
| | | logger.error(String.format("failed to call plugin.onDeletion %s", user.username), t); |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected void callDeleteTeamListeners(TeamModel team) { |
| | | if (pluginManager == null || team == null) { |
| | | return; |
| | | } |
| | | |
| | | for (UserTeamLifeCycleListener listener : pluginManager.getExtensions(UserTeamLifeCycleListener.class)) { |
| | | try { |
| | | listener.onDeletion(team); |
| | | } catch (Throwable t) { |
| | | logger.error(String.format("failed to call plugin.onDeletion %s", team.name), t); |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.gitblit.models; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | import org.apache.wicket.PageParameters; |
| | | import org.apache.wicket.markup.html.WebPage; |
| | | |
| | | import com.gitblit.utils.StringUtils; |
| | | |
| | | public class Menu { |
| | | |
| | | /** |
| | | * A MenuItem for a drop down menu. |
| | | * |
| | | * @author James Moger |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract static class MenuItem implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | final String displayText; |
| | | |
| | | MenuItem(String displayText) { |
| | | this.displayText = displayText; |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() { |
| | | return displayText.hashCode(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean equals(Object o) { |
| | | if (o instanceof MenuItem) { |
| | | return hashCode() == o.hashCode(); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return displayText; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * A divider for the menu. |
| | | * |
| | | * @since 1.6.0 |
| | | */ |
| | | public static class MenuDivider extends MenuItem { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public MenuDivider() { |
| | | super(""); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * A MenuItem for setting a parameter of the current url. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public static class ParameterMenuItem extends MenuItem { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | final PageParameters parameters; |
| | | final String parameter; |
| | | final String value; |
| | | final boolean isSelected; |
| | | |
| | | /** |
| | | * @param displayText |
| | | */ |
| | | public ParameterMenuItem(String displayText) { |
| | | this(displayText, null, null, null); |
| | | } |
| | | |
| | | /** |
| | | * @param displayText |
| | | * @param parameter |
| | | * @param value |
| | | */ |
| | | public ParameterMenuItem(String displayText, String parameter, String value) { |
| | | this(displayText, parameter, value, null); |
| | | } |
| | | |
| | | /** |
| | | * @param displayText |
| | | * @param parameter |
| | | * @param value |
| | | */ |
| | | public ParameterMenuItem(String displayText, String parameter, String value, |
| | | PageParameters params) { |
| | | super(displayText); |
| | | this.parameter = parameter; |
| | | this.value = value; |
| | | |
| | | if (params == null) { |
| | | // no parameters specified |
| | | parameters = new PageParameters(); |
| | | setParameter(parameter, value); |
| | | isSelected = false; |
| | | } else { |
| | | parameters = new PageParameters(params); |
| | | if (parameters.containsKey(parameter)) { |
| | | isSelected = params.getString(parameter).equals(value); |
| | | // set the new selection value |
| | | setParameter(parameter, value); |
| | | } else { |
| | | // not currently selected |
| | | isSelected = false; |
| | | setParameter(parameter, value); |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected void setParameter(String parameter, String value) { |
| | | if (!StringUtils.isEmpty(parameter)) { |
| | | if (StringUtils.isEmpty(value)) { |
| | | this.parameters.remove(parameter); |
| | | } else { |
| | | this.parameters.put(parameter, value); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public String formatParameter() { |
| | | if (StringUtils.isEmpty(parameter) || StringUtils.isEmpty(value)) { |
| | | return ""; |
| | | } |
| | | return parameter + "=" + value; |
| | | } |
| | | |
| | | public PageParameters getPageParameters() { |
| | | return parameters; |
| | | } |
| | | |
| | | public boolean isSelected() { |
| | | return isSelected; |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() { |
| | | if (StringUtils.isEmpty(displayText)) { |
| | | return value.hashCode() + parameter.hashCode(); |
| | | } |
| | | return displayText.hashCode(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean equals(Object o) { |
| | | if (o instanceof MenuItem) { |
| | | return hashCode() == o.hashCode(); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | if (StringUtils.isEmpty(displayText)) { |
| | | return formatParameter(); |
| | | } |
| | | return displayText; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Menu item for toggling a parameter. |
| | | * |
| | | */ |
| | | public static class ToggleMenuItem extends ParameterMenuItem { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * @param displayText |
| | | * @param parameter |
| | | * @param value |
| | | */ |
| | | public ToggleMenuItem(String displayText, String parameter, String value, |
| | | PageParameters params) { |
| | | super(displayText, parameter, value, params); |
| | | if (isSelected) { |
| | | // already selected, so remove this enables toggling |
| | | parameters.remove(parameter); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Menu item for linking to another Wicket page. |
| | | * |
| | | * @since 1.6.0 |
| | | */ |
| | | public static class PageLinkMenuItem extends MenuItem { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private final Class<? extends WebPage> pageClass; |
| | | |
| | | private final PageParameters params; |
| | | |
| | | /** |
| | | * Page Link Item links to another page. |
| | | * |
| | | * @param displayText |
| | | * @param pageClass |
| | | * @since 1.6.0 |
| | | */ |
| | | public PageLinkMenuItem(String displayText, Class<? extends WebPage> pageClass) { |
| | | this(displayText, pageClass, null); |
| | | } |
| | | |
| | | /** |
| | | * Page Link Item links to another page. |
| | | * |
| | | * @param displayText |
| | | * @param pageClass |
| | | * @param params |
| | | * @since 1.6.0 |
| | | */ |
| | | public PageLinkMenuItem(String displayText, Class<? extends WebPage> pageClass, PageParameters params) { |
| | | super(displayText); |
| | | this.pageClass = pageClass; |
| | | this.params = params; |
| | | } |
| | | |
| | | /** |
| | | * @return the page class |
| | | * @since 1.6.0 |
| | | */ |
| | | public Class<? extends WebPage> getPageClass() { |
| | | return pageClass; |
| | | } |
| | | |
| | | /** |
| | | * @return the page parameters |
| | | * @since 1.6.0 |
| | | */ |
| | | public PageParameters getPageParameters() { |
| | | return params; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Menu item to link to an external page. |
| | | * |
| | | * @since 1.6.0 |
| | | */ |
| | | public static class ExternalLinkMenuItem extends MenuItem { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private final String href; |
| | | |
| | | private final boolean newWindow; |
| | | |
| | | /** |
| | | * External Link Item links to something else. |
| | | * |
| | | * @param displayText |
| | | * @param href |
| | | * @since 1.6.0 |
| | | */ |
| | | public ExternalLinkMenuItem(String displayText, String href) { |
| | | this(displayText, href, false); |
| | | } |
| | | |
| | | /** |
| | | * External Link Item links to something else. |
| | | * |
| | | * @param displayText |
| | | * @param href |
| | | * @since 1.6.0 |
| | | */ |
| | | public ExternalLinkMenuItem(String displayText, String href, boolean newWindow) { |
| | | super(displayText); |
| | | this.href = href; |
| | | this.newWindow = newWindow; |
| | | } |
| | | |
| | | /** |
| | | * @since 1.6.0 |
| | | */ |
| | | public String getHref() { |
| | | return href; |
| | | } |
| | | |
| | | /** |
| | | * @since 1.6.0 |
| | | */ |
| | | public boolean openInNewWindow() { |
| | | return newWindow; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | /*
|
| | | * 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.models;
|
| | |
|
| | | import java.io.Serializable;
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.WebPage;
|
| | |
|
| | | import com.gitblit.models.Menu.MenuItem;
|
| | |
|
| | | /**
|
| | | * Represents a navigation link for the navigation panel.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public abstract class NavLink implements Serializable {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public final String translationKey;
|
| | | public final boolean hiddenPhone;
|
| | |
|
| | | public NavLink(String translationKey, boolean hiddenPhone) {
|
| | | this.translationKey = translationKey;
|
| | | this.hiddenPhone = hiddenPhone;
|
| | | }
|
| | |
|
| | |
|
| | | /**
|
| | | * Represents a Wicket page link.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public static class PageNavLink extends NavLink implements Serializable {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public final Class<? extends WebPage> pageClass;
|
| | | public final PageParameters params;
|
| | |
|
| | | public PageNavLink(String translationKey, Class<? extends WebPage> pageClass) {
|
| | | this(translationKey, pageClass, null);
|
| | | }
|
| | |
|
| | | public PageNavLink(String translationKey, Class<? extends WebPage> pageClass,
|
| | | PageParameters params) {
|
| | | this(translationKey, pageClass, params, false);
|
| | | }
|
| | |
|
| | | public PageNavLink(String translationKey, Class<? extends WebPage> pageClass,
|
| | | PageParameters params, boolean hiddenPhone) {
|
| | | super(translationKey, hiddenPhone);
|
| | | this.pageClass = pageClass;
|
| | | this.params = params;
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * Represents an explicitly href link.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public static class ExternalNavLink extends NavLink implements Serializable {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public final String url;
|
| | |
|
| | | public ExternalNavLink(String keyOrText, String url) {
|
| | | super(keyOrText, false);
|
| | | this.url = url;
|
| | | }
|
| | |
|
| | | public ExternalNavLink(String keyOrText, String url, boolean hiddenPhone) {
|
| | | super(keyOrText, hiddenPhone);
|
| | | this.url = url;
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * Represents a DropDownMenu for the current page.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public static class DropDownPageMenuNavLink extends PageNavLink implements Serializable {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public final List<MenuItem> menuItems;
|
| | |
|
| | | public DropDownPageMenuNavLink(String keyOrText, Class<? extends WebPage> pageClass) {
|
| | | this(keyOrText, pageClass, false);
|
| | | }
|
| | |
|
| | | public DropDownPageMenuNavLink(String keyOrText, Class<? extends WebPage> pageClass, boolean hiddenPhone) {
|
| | | super(keyOrText, pageClass, null, hiddenPhone);
|
| | | menuItems = new ArrayList<MenuItem>();
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * Represents a DropDownMenu.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public static class DropDownMenuNavLink extends NavLink implements Serializable {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public final List<MenuItem> menuItems;
|
| | |
|
| | | public DropDownMenuNavLink(String keyOrText) {
|
| | | this(keyOrText, false);
|
| | | }
|
| | |
|
| | | public DropDownMenuNavLink(String keyOrText, boolean hiddenPhone) {
|
| | | super(keyOrText, hiddenPhone);
|
| | | menuItems = new ArrayList<MenuItem>();
|
| | | }
|
| | | }
|
| | | } |
| | |
| | | import java.util.Map; |
| | | import java.util.TreeMap; |
| | | |
| | | import com.gitblit.Constants.Transport; |
| | | import com.gitblit.utils.StringUtils; |
| | | |
| | | /** |
| | |
| | | |
| | | public final String username; |
| | | |
| | | public String locale; |
| | | private String locale; |
| | | |
| | | private Boolean emailMeOnMyTicketChanges; |
| | | |
| | | private Transport transport; |
| | | |
| | | private final Map<String, UserRepositoryPreferences> repositoryPreferences = new TreeMap<String, UserRepositoryPreferences>(); |
| | | |
| | |
| | | return new Locale(lang, cc); |
| | | } |
| | | return new Locale(locale); |
| | | } |
| | | |
| | | public void setLocale(String locale) { |
| | | this.locale = locale; |
| | | } |
| | | |
| | | public UserRepositoryPreferences getRepositoryPreferences(String repositoryName) { |
| | |
| | | Collections.sort(list); |
| | | return list; |
| | | } |
| | | |
| | | public boolean isEmailMeOnMyTicketChanges() { |
| | | if (emailMeOnMyTicketChanges == null) { |
| | | return true; |
| | | } |
| | | return emailMeOnMyTicketChanges; |
| | | } |
| | | |
| | | public void setEmailMeOnMyTicketChanges(boolean value) { |
| | | this.emailMeOnMyTicketChanges = value; |
| | | } |
| | | |
| | | public Transport getTransport() { |
| | | return transport; |
| | | } |
| | | |
| | | public void setTransport(Transport transport) { |
| | | this.transport = transport; |
| | | } |
| | | } |
| | |
| | | final String mailUser = settings.getString(Keys.mail.username, null);
|
| | | final String mailPassword = settings.getString(Keys.mail.password, null);
|
| | | final boolean smtps = settings.getBoolean(Keys.mail.smtps, false);
|
| | | final boolean starttls = settings.getBoolean(Keys.mail.starttls, false);
|
| | | boolean authenticate = !StringUtils.isEmpty(mailUser) && !StringUtils.isEmpty(mailPassword);
|
| | | String server = settings.getString(Keys.mail.server, "");
|
| | | if (StringUtils.isEmpty(server)) {
|
| | |
| | | props.setProperty("mail.smtp.port", String.valueOf(port));
|
| | | props.setProperty("mail.smtp.auth", String.valueOf(authenticate));
|
| | | props.setProperty("mail.smtp.auths", String.valueOf(authenticate));
|
| | | props.setProperty("mail.smtp.starttls.enable", String.valueOf(starttls));
|
| | |
|
| | | if (isGMail || smtps) {
|
| | | props.setProperty("mail.smtp.starttls.enable", "true");
|
| | |
| | | import java.text.MessageFormat;
|
| | |
|
| | | import javax.servlet.FilterChain;
|
| | | import javax.servlet.FilterConfig;
|
| | | import javax.servlet.ServletException;
|
| | | import javax.servlet.ServletRequest;
|
| | | import javax.servlet.ServletResponse;
|
| | |
| | | protected IRepositoryManager repositoryManager;
|
| | |
|
| | | @Override
|
| | | protected void inject(ObjectGraph dagger) {
|
| | | super.inject(dagger);
|
| | | protected void inject(ObjectGraph dagger, FilterConfig filterConfig) {
|
| | | super.inject(dagger, filterConfig);
|
| | | this.runtimeManager = dagger.get(IRuntimeManager.class);
|
| | | this.repositoryManager = dagger.get(IRepositoryManager.class);
|
| | | }
|
| | |
| | | import java.util.Map;
|
| | |
|
| | | import javax.servlet.FilterChain;
|
| | | import javax.servlet.FilterConfig;
|
| | | import javax.servlet.ServletException;
|
| | | import javax.servlet.ServletRequest;
|
| | | import javax.servlet.ServletResponse;
|
| | |
| | | protected IAuthenticationManager authenticationManager;
|
| | |
|
| | | @Override
|
| | | protected void inject(ObjectGraph dagger) {
|
| | | protected void inject(ObjectGraph dagger, FilterConfig filterConfig) {
|
| | | this.authenticationManager = dagger.get(IAuthenticationManager.class);
|
| | | }
|
| | |
|
| | |
| | | import java.text.MessageFormat; |
| | | |
| | | import javax.servlet.FilterChain; |
| | | import javax.servlet.FilterConfig; |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.ServletRequest; |
| | | import javax.servlet.ServletResponse; |
| | |
| | | private IAuthenticationManager authenticationManager; |
| | | |
| | | @Override |
| | | protected void inject(ObjectGraph dagger) { |
| | | protected void inject(ObjectGraph dagger, FilterConfig filterConfig) { |
| | | this.settings = dagger.get(IStoredSettings.class); |
| | | this.authenticationManager = dagger.get(IAuthenticationManager.class); |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.servlet; |
| | | |
| | | import java.util.Enumeration; |
| | | |
| | | import javax.servlet.FilterConfig; |
| | | import javax.servlet.ServletContext; |
| | | |
| | | import com.gitblit.IStoredSettings; |
| | | import com.gitblit.manager.IRuntimeManager; |
| | | |
| | | /** |
| | | * Wraps a filter config and will prefer a setting retrieved from IStoredSettings |
| | | * if one is available. |
| | | * |
| | | * @author James Moger |
| | | * @since 1.6.0 |
| | | */ |
| | | public class FilterRuntimeConfig implements FilterConfig { |
| | | |
| | | final IRuntimeManager runtime; |
| | | final IStoredSettings settings; |
| | | final String namespace; |
| | | final FilterConfig config; |
| | | |
| | | public FilterRuntimeConfig(IRuntimeManager runtime, String namespace, FilterConfig config) { |
| | | this.runtime = runtime; |
| | | this.settings = runtime.getSettings(); |
| | | this.namespace = namespace; |
| | | this.config = config; |
| | | } |
| | | |
| | | @Override |
| | | public String getFilterName() { |
| | | return config.getFilterName(); |
| | | } |
| | | |
| | | @Override |
| | | public ServletContext getServletContext() { |
| | | return config.getServletContext(); |
| | | } |
| | | |
| | | @Override |
| | | public String getInitParameter(String name) { |
| | | String key = namespace + "." + name; |
| | | if (settings.hasSettings(key)) { |
| | | String value = settings.getString(key, null); |
| | | return value; |
| | | } |
| | | return config.getInitParameter(name); |
| | | } |
| | | |
| | | @Override |
| | | public Enumeration<String> getInitParameterNames() { |
| | | return config.getInitParameterNames(); |
| | | } |
| | | } |
| | |
| | |
|
| | | import java.text.MessageFormat;
|
| | |
|
| | | import javax.servlet.FilterConfig;
|
| | | import javax.servlet.http.HttpServletRequest;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | |
| | | private IFederationManager federationManager;
|
| | |
|
| | | @Override
|
| | | protected void inject(ObjectGraph dagger) {
|
| | | super.inject(dagger);
|
| | | protected void inject(ObjectGraph dagger, FilterConfig filterConfig) {
|
| | | super.inject(dagger, filterConfig);
|
| | | this.settings = dagger.get(IStoredSettings.class);
|
| | | this.federationManager = dagger.get(IFederationManager.class);
|
| | | }
|
| | |
| | | import com.gitblit.Keys; |
| | | import com.gitblit.WebXmlSettings; |
| | | import com.gitblit.dagger.DaggerContext; |
| | | import com.gitblit.extensions.LifeCycleListener; |
| | | import com.gitblit.manager.IAuthenticationManager; |
| | | import com.gitblit.manager.IFederationManager; |
| | | import com.gitblit.manager.IGitblit; |
| | |
| | | runtime.start(); |
| | | managers.add(runtime); |
| | | |
| | | // create the plugin manager instance but do not start it |
| | | loadManager(injector, IPluginManager.class); |
| | | |
| | | // start all other managers |
| | | startManager(injector, INotificationManager.class); |
| | | startManager(injector, IUserManager.class); |
| | |
| | | logger.info(""); |
| | | logger.info("All managers started."); |
| | | logger.info(""); |
| | | |
| | | IPluginManager pluginManager = injector.get(IPluginManager.class); |
| | | for (LifeCycleListener listener : pluginManager.getExtensions(LifeCycleListener.class)) { |
| | | try { |
| | | listener.onStartup(); |
| | | } catch (Throwable t) { |
| | | logger.error(null, t); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private String lookupBaseFolderFromJndi() { |
| | |
| | | return null; |
| | | } |
| | | |
| | | protected <X extends IManager> X startManager(ObjectGraph injector, Class<X> clazz) { |
| | | logManager(clazz); |
| | | protected <X extends IManager> X loadManager(ObjectGraph injector, Class<X> clazz) { |
| | | X x = injector.get(clazz); |
| | | return x; |
| | | } |
| | | |
| | | protected <X extends IManager> X startManager(ObjectGraph injector, Class<X> clazz) { |
| | | X x = loadManager(injector, clazz); |
| | | logManager(clazz); |
| | | x.start(); |
| | | managers.add(x); |
| | | return x; |
| | |
| | | @Override |
| | | protected void destroyContext(ServletContext context) { |
| | | logger.info("Gitblit context destroyed by servlet container."); |
| | | |
| | | IPluginManager pluginManager = getManager(IPluginManager.class); |
| | | for (LifeCycleListener listener : pluginManager.getExtensions(LifeCycleListener.class)) { |
| | | try { |
| | | listener.onShutdown(); |
| | | } catch (Throwable t) { |
| | | logger.error(null, t); |
| | | } |
| | | } |
| | | |
| | | for (IManager manager : managers) { |
| | | logger.debug("stopping {}", manager.getClass().getSimpleName()); |
| | | manager.stop(); |
| | |
| | | } |
| | | } |
| | | |
| | | // Copy the included gitignore files to the configured gitignore folder |
| | | String gitignorePath = webxmlSettings.getString(Keys.git.gitignoreFolder, "gitignore"); |
| | | File localGitignores = com.gitblit.utils.FileUtils.resolveParameter(Constants.baseFolder$, base, gitignorePath); |
| | | if (!localGitignores.exists()) { |
| | | File warGitignores = new File(contextFolder, "/WEB-INF/data/gitignore"); |
| | | if (!warGitignores.equals(localGitignores)) { |
| | | try { |
| | | com.gitblit.utils.FileUtils.copy(localGitignores, warGitignores.listFiles()); |
| | | } catch (IOException e) { |
| | | logger.error(MessageFormat.format( |
| | | "Failed to copy included .gitignore files from {0} to {1}", |
| | | warGitignores, localGitignores)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // merge the WebXmlSettings into the runtime settings (for backwards-compatibilty) |
| | | runtimeSettings.merge(webxmlSettings); |
| | | |
| | |
| | | */
|
| | | package com.gitblit.servlet;
|
| | |
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | |
|
| | | /**
|
| | | * The PagesFilter is an AccessRestrictionFilter which ensures the gh-pages
|
| | |
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class PagesFilter extends AccessRestrictionFilter {
|
| | | public class PagesFilter extends RawFilter {
|
| | |
|
| | | /**
|
| | | * Extract the repository name from the url.
|
| | | *
|
| | | * @param url
|
| | | * @return repository name
|
| | | */
|
| | | @Override
|
| | | protected String extractRepositoryName(String url) {
|
| | | // get the repository name from the url by finding a known url suffix
|
| | | String repository = "";
|
| | | Repository r = null;
|
| | | int offset = 0;
|
| | | while (r == null) {
|
| | | int slash = url.indexOf('/', offset);
|
| | | if (slash == -1) {
|
| | | repository = url;
|
| | | } else {
|
| | | repository = url.substring(0, slash);
|
| | | }
|
| | | r = repositoryManager.getRepository(repository, false);
|
| | | if (r == null) {
|
| | | // try again
|
| | | offset = slash + 1;
|
| | | } else {
|
| | | // close the repo
|
| | | r.close();
|
| | | }
|
| | | if (repository.equals(url)) {
|
| | | // either only repository in url or no repository found
|
| | | break;
|
| | | }
|
| | | }
|
| | | return repository;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Analyze the url and returns the action of the request.
|
| | | *
|
| | | * @param cloneUrl
|
| | | * @return action of the request
|
| | | */
|
| | | @Override
|
| | | protected String getUrlRequestAction(String suffix) {
|
| | | return "VIEW";
|
| | | }
|
| | |
|
| | | /**
|
| | | * Determine if a non-existing repository can be created using this filter.
|
| | | *
|
| | | * @return true if the filter allows repository creation
|
| | | */
|
| | | @Override
|
| | | protected boolean isCreationAllowed() {
|
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Determine if the action may be executed on the repository.
|
| | | *
|
| | | * @param repository
|
| | | * @param action
|
| | | * @return true if the action may be performed
|
| | | */
|
| | | @Override
|
| | | protected boolean isActionAllowed(RepositoryModel repository, String action) {
|
| | | return true;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Determine if the repository requires authentication.
|
| | | *
|
| | | * @param repository
|
| | | * @param action
|
| | | * @return true if authentication required
|
| | | */
|
| | | @Override
|
| | | protected boolean requiresAuthentication(RepositoryModel repository, String action) {
|
| | | return repository.accessRestriction.atLeast(AccessRestrictionType.VIEW);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Determine if the user can access the repository and perform the specified
|
| | | * action.
|
| | | *
|
| | | * @param repository
|
| | | * @param user
|
| | | * @param action
|
| | | * @return true if user may execute the action on the repository
|
| | | */
|
| | | @Override
|
| | | protected boolean canAccess(RepositoryModel repository, UserModel user, String action) {
|
| | | return user.canView(repository);
|
| | | }
|
| | | }
|
| | |
| | | */
|
| | | package com.gitblit.servlet;
|
| | |
|
| | | import java.io.IOException;
|
| | | import java.text.MessageFormat;
|
| | | import java.text.ParseException;
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | | import java.util.TreeMap;
|
| | |
|
| | | import javax.servlet.ServletContext;
|
| | | import javax.servlet.ServletException;
|
| | | import javax.servlet.http.HttpServletRequest;
|
| | | import javax.servlet.http.HttpServletResponse;
|
| | |
|
| | | import org.eclipse.jgit.lib.FileMode;
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | | import org.eclipse.jgit.revwalk.RevTree;
|
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
|
| | | import com.gitblit.Constants;
|
| | | import com.gitblit.IStoredSettings;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.dagger.DaggerServlet;
|
| | | import com.gitblit.manager.IRepositoryManager;
|
| | | import com.gitblit.models.PathModel;
|
| | | import com.gitblit.models.RefModel;
|
| | | import com.gitblit.utils.ArrayUtils;
|
| | | import com.gitblit.utils.ByteFormat;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.MarkdownUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.MarkupProcessor;
|
| | | import com.gitblit.wicket.MarkupProcessor.MarkupDocument;
|
| | |
|
| | | import dagger.ObjectGraph;
|
| | |
|
| | | /**
|
| | | * Serves the content of a gh-pages branch.
|
| | |
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class PagesServlet extends DaggerServlet {
|
| | | public class PagesServlet extends RawServlet {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | private transient Logger logger = LoggerFactory.getLogger(PagesServlet.class);
|
| | |
|
| | | private IStoredSettings settings;
|
| | |
|
| | | private IRepositoryManager repositoryManager;
|
| | |
|
| | | @Override
|
| | | protected void inject(ObjectGraph dagger) {
|
| | | this.settings = dagger.get(IStoredSettings.class);
|
| | | this.repositoryManager = dagger.get(IRepositoryManager.class);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns an url to this servlet for the specified parameters.
|
| | |
| | | return baseURL + Constants.PAGES + repository + "/" + (path == null ? "" : ("/" + path));
|
| | | }
|
| | |
|
| | | /**
|
| | | * Retrieves the specified resource from the gh-pages branch of the
|
| | | * repository.
|
| | | *
|
| | | * @param request
|
| | | * @param response
|
| | | * @throws javax.servlet.ServletException
|
| | | * @throws java.io.IOException
|
| | | */
|
| | | private void processRequest(HttpServletRequest request, HttpServletResponse response)
|
| | | throws ServletException, IOException {
|
| | | String path = request.getPathInfo();
|
| | | if (path.toLowerCase().endsWith(".git")) {
|
| | | // forward to url with trailing /
|
| | | // this is important for relative pages links
|
| | | response.sendRedirect(request.getServletPath() + path + "/");
|
| | | return;
|
| | | }
|
| | | if (path.charAt(0) == '/') {
|
| | | // strip leading /
|
| | | path = path.substring(1);
|
| | | }
|
| | |
|
| | | // determine repository and resource from url
|
| | | String repository = "";
|
| | | String resource = "";
|
| | | Repository r = null;
|
| | | int offset = 0;
|
| | | while (r == null) {
|
| | | int slash = path.indexOf('/', offset);
|
| | | if (slash == -1) {
|
| | | repository = path;
|
| | | } else {
|
| | | repository = path.substring(0, slash);
|
| | | }
|
| | | r = repositoryManager.getRepository(repository, false);
|
| | | offset = slash + 1;
|
| | | if (offset > 0) {
|
| | | resource = path.substring(offset);
|
| | | }
|
| | | if (repository.equals(path)) {
|
| | | // either only repository in url or no repository found
|
| | | break;
|
| | | }
|
| | | }
|
| | |
|
| | | ServletContext context = request.getSession().getServletContext();
|
| | |
|
| | | try {
|
| | | if (r == null) {
|
| | | // repository not found!
|
| | | String mkd = MessageFormat.format(
|
| | | "# Error\nSorry, no valid **repository** specified in this url: {0}!",
|
| | | repository);
|
| | | error(response, mkd);
|
| | | return;
|
| | | }
|
| | |
|
| | | // retrieve the content from the repository
|
| | | RefModel pages = JGitUtils.getPagesBranch(r);
|
| | | RevCommit commit = JGitUtils.getCommit(r, pages.getObjectId().getName());
|
| | |
|
| | | if (commit == null) {
|
| | | // branch not found!
|
| | | String mkd = MessageFormat.format(
|
| | | "# Error\nSorry, the repository {0} does not have a **gh-pages** branch!",
|
| | | repository);
|
| | | error(response, mkd);
|
| | | return;
|
| | | }
|
| | |
|
| | | MarkupProcessor processor = new MarkupProcessor(settings);
|
| | | String [] encodings = settings.getStrings(Keys.web.blobEncodings).toArray(new String[0]);
|
| | |
|
| | | RevTree tree = commit.getTree();
|
| | |
|
| | | String res = resource;
|
| | | if (res.endsWith("/")) {
|
| | | res = res.substring(0, res.length() - 1);
|
| | | }
|
| | |
|
| | | List<PathModel> pathEntries = JGitUtils.getFilesInPath(r, res, commit);
|
| | |
|
| | | byte[] content = null;
|
| | | if (pathEntries.isEmpty()) {
|
| | | // not a path, a specific resource
|
| | | try {
|
| | | String contentType = context.getMimeType(res);
|
| | | if (contentType == null) {
|
| | | contentType = "text/plain";
|
| | | }
|
| | | if (contentType.startsWith("text")) {
|
| | | content = JGitUtils.getStringContent(r, tree, res, encodings).getBytes(
|
| | | Constants.ENCODING);
|
| | | } else {
|
| | | content = JGitUtils.getByteContent(r, tree, res, false);
|
| | | }
|
| | | response.setContentType(contentType);
|
| | | } catch (Exception e) {
|
| | | }
|
| | | } else {
|
| | | // path request
|
| | | if (!request.getPathInfo().endsWith("/")) {
|
| | | // redirect to trailing '/' url
|
| | | response.sendRedirect(request.getServletPath() + request.getPathInfo() + "/");
|
| | | return;
|
| | | }
|
| | |
|
| | | Map<String, String> names = new TreeMap<String, String>();
|
| | | for (PathModel entry : pathEntries) {
|
| | | names.put(entry.name.toLowerCase(), entry.name);
|
| | | }
|
| | |
|
| | | List<String> extensions = new ArrayList<String>();
|
| | | extensions.add("html");
|
| | | extensions.add("htm");
|
| | | extensions.addAll(processor.getMarkupExtensions());
|
| | | for (String ext : extensions) {
|
| | | String key = "index." + ext;
|
| | |
|
| | | if (names.containsKey(key)) {
|
| | | String fileName = names.get(key);
|
| | | String fullPath = fileName;
|
| | | if (!res.isEmpty()) {
|
| | | fullPath = res + "/" + fileName;
|
| | | }
|
| | | String stringContent = JGitUtils.getStringContent(r, tree, fullPath, encodings);
|
| | | if (stringContent == null) {
|
| | | continue;
|
| | | }
|
| | | content = stringContent.getBytes(Constants.ENCODING);
|
| | | if (content != null) {
|
| | | res = fullPath;
|
| | | // assume text/html unless the servlet container
|
| | | // overrides
|
| | | response.setContentType("text/html; charset=" + Constants.ENCODING);
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | // no content, document list or custom 404 page
|
| | | if (ArrayUtils.isEmpty(content)) {
|
| | | if (pathEntries.isEmpty()) {
|
| | | // 404
|
| | | String custom404 = JGitUtils.getStringContent(r, tree, "404.html", encodings);
|
| | | if (!StringUtils.isEmpty(custom404)) {
|
| | | content = custom404.getBytes(Constants.ENCODING);
|
| | | }
|
| | |
|
| | | // still no content
|
| | | if (ArrayUtils.isEmpty(content)) {
|
| | | String str = MessageFormat.format(
|
| | | "# Error\nSorry, the requested resource **{0}** was not found.",
|
| | | resource);
|
| | | content = MarkdownUtils.transformMarkdown(str).getBytes(Constants.ENCODING);
|
| | | }
|
| | |
|
| | | try {
|
| | | // output the content
|
| | | logger.warn("Pages 404: " + resource);
|
| | | response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
| | | response.getOutputStream().write(content);
|
| | | response.flushBuffer();
|
| | | } catch (Throwable t) {
|
| | | logger.error("Failed to write page to client", t);
|
| | | }
|
| | | } else {
|
| | | // document list
|
| | | response.setContentType("text/html");
|
| | | response.getWriter().append("<style>table th, table td { min-width: 150px; text-align: left; }</style>");
|
| | | response.getWriter().append("<table>");
|
| | | response.getWriter().append("<thead><tr><th>path</th><th>mode</th><th>size</th></tr>");
|
| | | response.getWriter().append("</thead>");
|
| | | response.getWriter().append("<tbody>");
|
| | | String pattern = "<tr><td><a href=\"{0}/{1}\">{1}</a></td><td>{2}</td><td>{3}</td></tr>";
|
| | | final ByteFormat byteFormat = new ByteFormat();
|
| | | if (!pathEntries.isEmpty()) {
|
| | | if (pathEntries.get(0).path.indexOf('/') > -1) {
|
| | | // we are in a subdirectory, add parent directory link
|
| | | pathEntries.add(0, new PathModel("..", resource + "/..", 0, FileMode.TREE.getBits(), null, null));
|
| | | }
|
| | | }
|
| | |
|
| | | String basePath = request.getServletPath() + request.getPathInfo();
|
| | | if (basePath.charAt(basePath.length() - 1) == '/') {
|
| | | // strip trailing slash
|
| | | basePath = basePath.substring(0, basePath.length() - 1);
|
| | | }
|
| | | for (PathModel entry : pathEntries) {
|
| | | response.getWriter().append(MessageFormat.format(pattern, basePath, entry.name,
|
| | | JGitUtils.getPermissionsFromMode(entry.mode), byteFormat.format(entry.size)));
|
| | | }
|
| | | response.getWriter().append("</tbody>");
|
| | | response.getWriter().append("</table>");
|
| | | }
|
| | | return;
|
| | | }
|
| | |
|
| | | // check to see if we should transform markup files
|
| | | String ext = StringUtils.getFileExtension(resource);
|
| | | if (processor.getMarkupExtensions().contains(ext)) {
|
| | | String markup = new String(content, Constants.ENCODING);
|
| | | MarkupDocument markupDoc = processor.parse(repository, commit.getName(), resource, markup);
|
| | | content = markupDoc.html.getBytes("UTF-8");
|
| | | response.setContentType("text/html; charset=" + Constants.ENCODING);
|
| | | }
|
| | |
|
| | | try {
|
| | | // output the content
|
| | | response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate");
|
| | | response.setDateHeader("Last-Modified", JGitUtils.getCommitDate(commit).getTime());
|
| | | response.getOutputStream().write(content);
|
| | | response.flushBuffer();
|
| | | } catch (Throwable t) {
|
| | | logger.error("Failed to write page to client", t);
|
| | | }
|
| | |
|
| | | } catch (Throwable t) {
|
| | | logger.error("Failed to write page to client", t);
|
| | | } finally {
|
| | | r.close();
|
| | | }
|
| | | }
|
| | |
|
| | | private void error(HttpServletResponse response, String mkd) throws ServletException,
|
| | | IOException, ParseException {
|
| | | String content = MarkdownUtils.transformMarkdown(mkd);
|
| | | response.setContentType("text/html; charset=" + Constants.ENCODING);
|
| | | response.getWriter().write(content);
|
| | | @Override
|
| | | protected String getBranch(String repository, HttpServletRequest request) {
|
| | | return "gh-pages";
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void doPost(HttpServletRequest request, HttpServletResponse response)
|
| | | throws ServletException, IOException {
|
| | | processRequest(request, response);
|
| | | protected String getPath(String repository, String branch, HttpServletRequest request) {
|
| | | String pi = request.getPathInfo().substring(1);
|
| | | if (pi.equals(repository)) {
|
| | | return "";
|
| | | }
|
| | | String path = pi.substring(pi.indexOf(repository) + repository.length() + 1);
|
| | | if (path.endsWith("/")) {
|
| | | path = path.substring(0, path.length() - 1);
|
| | | }
|
| | | return path;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
| | | throws ServletException, IOException {
|
| | | processRequest(request, response);
|
| | | protected boolean renderIndex() {
|
| | | return true;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void setContentType(HttpServletResponse response, String contentType) {
|
| | | response.setContentType(contentType);;
|
| | | }
|
| | | }
|
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.servlet; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | |
| | | import javax.servlet.FilterChain; |
| | | import javax.servlet.FilterConfig; |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.ServletRequest; |
| | | import javax.servlet.ServletResponse; |
| | | |
| | | import ro.fortsoft.pf4j.PluginWrapper; |
| | | |
| | | import com.gitblit.dagger.DaggerFilter; |
| | | import com.gitblit.extensions.HttpRequestFilter; |
| | | import com.gitblit.manager.IPluginManager; |
| | | import com.gitblit.manager.IRuntimeManager; |
| | | |
| | | import dagger.ObjectGraph; |
| | | |
| | | /** |
| | | * A request filter than allows registered extension request filters to access |
| | | * request data. The intended purpose is for server monitoring plugins. |
| | | * |
| | | * @author David Ostrovsky |
| | | * @since 1.6.0 |
| | | */ |
| | | public class ProxyFilter extends DaggerFilter { |
| | | private List<HttpRequestFilter> filters; |
| | | |
| | | @Override |
| | | protected void inject(ObjectGraph dagger, FilterConfig filterConfig) throws ServletException { |
| | | IRuntimeManager runtimeManager = dagger.get(IRuntimeManager.class); |
| | | IPluginManager pluginManager = dagger.get(IPluginManager.class); |
| | | |
| | | filters = pluginManager.getExtensions(HttpRequestFilter.class); |
| | | for (HttpRequestFilter f : filters) { |
| | | // wrap the filter config for Gitblit settings retrieval |
| | | PluginWrapper pluginWrapper = pluginManager.whichPlugin(f.getClass()); |
| | | FilterConfig runtimeConfig = new FilterRuntimeConfig(runtimeManager, |
| | | pluginWrapper.getPluginId(), filterConfig); |
| | | |
| | | f.init(runtimeConfig); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void doFilter(ServletRequest req, ServletResponse res, final FilterChain last) |
| | | throws IOException, ServletException { |
| | | final Iterator<HttpRequestFilter> itr = filters.iterator(); |
| | | new FilterChain() { |
| | | @Override |
| | | public void doFilter(ServletRequest req, ServletResponse res) throws IOException, |
| | | ServletException { |
| | | if (itr.hasNext()) { |
| | | itr.next().doFilter(req, res, this); |
| | | } else { |
| | | last.doFilter(req, res); |
| | | } |
| | | } |
| | | }.doFilter(req, res); |
| | | } |
| | | |
| | | @Override |
| | | public void destroy() { |
| | | for (HttpRequestFilter f : filters) { |
| | | f.destroy(); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | /*
|
| | | * Copyright 2012 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.servlet;
|
| | |
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | |
|
| | | /**
|
| | | * The RawFilter is an AccessRestrictionFilter which ensures http branch
|
| | | * requests for a view-restricted repository are authenticated and authorized.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class RawFilter extends AccessRestrictionFilter {
|
| | |
|
| | | /**
|
| | | * Extract the repository name from the url.
|
| | | *
|
| | | * @param url
|
| | | * @return repository name
|
| | | */
|
| | | @Override
|
| | | protected String extractRepositoryName(String url) {
|
| | | // get the repository name from the url by finding a known url suffix
|
| | | String repository = "";
|
| | | Repository r = null;
|
| | | int offset = 0;
|
| | | while (r == null) {
|
| | | int slash = url.indexOf('/', offset);
|
| | | if (slash == -1) {
|
| | | repository = url;
|
| | | } else {
|
| | | repository = url.substring(0, slash);
|
| | | }
|
| | | r = repositoryManager.getRepository(repository, false);
|
| | | if (r == null) {
|
| | | // try again
|
| | | offset = slash + 1;
|
| | | } else {
|
| | | // close the repo
|
| | | r.close();
|
| | | }
|
| | | if (repository.equals(url)) {
|
| | | // either only repository in url or no repository found
|
| | | break;
|
| | | }
|
| | | }
|
| | | return repository;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Analyze the url and returns the action of the request.
|
| | | *
|
| | | * @param cloneUrl
|
| | | * @return action of the request
|
| | | */
|
| | | @Override
|
| | | protected String getUrlRequestAction(String suffix) {
|
| | | return "VIEW";
|
| | | }
|
| | |
|
| | | /**
|
| | | * Determine if a non-existing repository can be created using this filter.
|
| | | *
|
| | | * @return true if the filter allows repository creation
|
| | | */
|
| | | @Override
|
| | | protected boolean isCreationAllowed() {
|
| | | return false;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Determine if the action may be executed on the repository.
|
| | | *
|
| | | * @param repository
|
| | | * @param action
|
| | | * @return true if the action may be performed
|
| | | */
|
| | | @Override
|
| | | protected boolean isActionAllowed(RepositoryModel repository, String action) {
|
| | | return true;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Determine if the repository requires authentication.
|
| | | *
|
| | | * @param repository
|
| | | * @param action
|
| | | * @return true if authentication required
|
| | | */
|
| | | @Override
|
| | | protected boolean requiresAuthentication(RepositoryModel repository, String action) {
|
| | | return repository.accessRestriction.atLeast(AccessRestrictionType.VIEW);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Determine if the user can access the repository and perform the specified
|
| | | * action.
|
| | | *
|
| | | * @param repository
|
| | | * @param user
|
| | | * @param action
|
| | | * @return true if user may execute the action on the repository
|
| | | */
|
| | | @Override
|
| | | protected boolean canAccess(RepositoryModel repository, UserModel user, String action) {
|
| | | return user.canView(repository);
|
| | | }
|
| | | }
|
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.servlet; |
| | | |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.net.URLEncoder; |
| | | import java.text.MessageFormat; |
| | | import java.text.ParseException; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.TreeMap; |
| | | |
| | | import javax.servlet.ServletContext; |
| | | import javax.servlet.ServletException; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import org.apache.tika.Tika; |
| | | import org.eclipse.jgit.lib.FileMode; |
| | | import org.eclipse.jgit.lib.MutableObjectId; |
| | | import org.eclipse.jgit.lib.ObjectLoader; |
| | | import org.eclipse.jgit.lib.ObjectReader; |
| | | import org.eclipse.jgit.lib.Repository; |
| | | import org.eclipse.jgit.revwalk.RevCommit; |
| | | import org.eclipse.jgit.revwalk.RevWalk; |
| | | import org.eclipse.jgit.treewalk.TreeWalk; |
| | | import org.eclipse.jgit.treewalk.filter.PathFilter; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import com.gitblit.Constants; |
| | | import com.gitblit.Keys; |
| | | import com.gitblit.dagger.DaggerServlet; |
| | | import com.gitblit.manager.IRepositoryManager; |
| | | import com.gitblit.manager.IRuntimeManager; |
| | | import com.gitblit.models.PathModel; |
| | | import com.gitblit.utils.ByteFormat; |
| | | import com.gitblit.utils.JGitUtils; |
| | | import com.gitblit.utils.MarkdownUtils; |
| | | import com.gitblit.utils.StringUtils; |
| | | |
| | | import dagger.ObjectGraph; |
| | | |
| | | /** |
| | | * Serves the content of a branch. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public class RawServlet extends DaggerServlet { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private transient Logger logger = LoggerFactory.getLogger(RawServlet.class); |
| | | |
| | | private IRuntimeManager runtimeManager; |
| | | |
| | | private IRepositoryManager repositoryManager; |
| | | |
| | | @Override |
| | | protected void inject(ObjectGraph dagger) { |
| | | this.runtimeManager = dagger.get(IRuntimeManager.class); |
| | | this.repositoryManager = dagger.get(IRepositoryManager.class); |
| | | } |
| | | |
| | | /** |
| | | * Returns an url to this servlet for the specified parameters. |
| | | * |
| | | * @param baseURL |
| | | * @param repository |
| | | * @param branch |
| | | * @param path |
| | | * @return an url |
| | | */ |
| | | public static String asLink(String baseURL, String repository, String branch, String path) { |
| | | if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') { |
| | | baseURL = baseURL.substring(0, baseURL.length() - 1); |
| | | } |
| | | |
| | | if (branch != null) { |
| | | char fsc = '!'; |
| | | char c = GitblitContext.getManager(IRuntimeManager.class).getSettings().getChar(Keys.web.forwardSlashCharacter, '/'); |
| | | if (c != '/') { |
| | | fsc = c; |
| | | } |
| | | branch = branch.replace('/', fsc); |
| | | } |
| | | |
| | | String encodedPath = path == null ? "" : path.replace(' ', '-'); |
| | | try { |
| | | encodedPath = URLEncoder.encode(encodedPath, "UTF-8"); |
| | | } catch (UnsupportedEncodingException e) { |
| | | } |
| | | return baseURL + Constants.RAW_PATH + repository + "/" + (branch == null ? "" : (branch + "/" + (path == null ? "" : encodedPath))); |
| | | } |
| | | |
| | | protected String getBranch(String repository, HttpServletRequest request) { |
| | | String pi = request.getPathInfo(); |
| | | String branch = pi.substring(pi.indexOf(repository) + repository.length() + 1); |
| | | int fs = branch.indexOf('/'); |
| | | if (fs > -1) { |
| | | branch = branch.substring(0, fs); |
| | | } |
| | | char c = runtimeManager.getSettings().getChar(Keys.web.forwardSlashCharacter, '/'); |
| | | return branch.replace('!', '/').replace(c, '/'); |
| | | } |
| | | |
| | | protected String getPath(String repository, String branch, HttpServletRequest request) { |
| | | String base = repository + "/" + branch; |
| | | String pi = request.getPathInfo().substring(1); |
| | | if (pi.equals(base)) { |
| | | return ""; |
| | | } |
| | | String path = pi.substring(pi.indexOf(base) + base.length() + 1); |
| | | if (path.endsWith("/")) { |
| | | path = path.substring(0, path.length() - 1); |
| | | } |
| | | return path; |
| | | } |
| | | |
| | | protected boolean renderIndex() { |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the specified resource from the specified branch of the |
| | | * repository. |
| | | * |
| | | * @param request |
| | | * @param response |
| | | * @throws javax.servlet.ServletException |
| | | * @throws java.io.IOException |
| | | */ |
| | | private void processRequest(HttpServletRequest request, HttpServletResponse response) |
| | | throws ServletException, IOException { |
| | | String path = request.getPathInfo(); |
| | | if (path.toLowerCase().endsWith(".git")) { |
| | | // forward to url with trailing / |
| | | // this is important for relative pages links |
| | | response.sendRedirect(request.getServletPath() + path + "/"); |
| | | return; |
| | | } |
| | | if (path.charAt(0) == '/') { |
| | | // strip leading / |
| | | path = path.substring(1); |
| | | } |
| | | |
| | | // determine repository and resource from url |
| | | String repository = ""; |
| | | Repository r = null; |
| | | int offset = 0; |
| | | while (r == null) { |
| | | int slash = path.indexOf('/', offset); |
| | | if (slash == -1) { |
| | | repository = path; |
| | | } else { |
| | | repository = path.substring(0, slash); |
| | | } |
| | | offset += slash; |
| | | r = repositoryManager.getRepository(repository, false); |
| | | if (repository.equals(path)) { |
| | | // either only repository in url or no repository found |
| | | break; |
| | | } |
| | | } |
| | | |
| | | ServletContext context = request.getSession().getServletContext(); |
| | | |
| | | try { |
| | | if (r == null) { |
| | | // repository not found! |
| | | String mkd = MessageFormat.format( |
| | | "# Error\nSorry, no valid **repository** specified in this url: {0}!", |
| | | path); |
| | | error(response, mkd); |
| | | return; |
| | | } |
| | | |
| | | // identify the branch |
| | | String branch = getBranch(repository, request); |
| | | if (StringUtils.isEmpty(branch)) { |
| | | branch = r.getBranch(); |
| | | if (branch == null) { |
| | | // no branches found! empty? |
| | | String mkd = MessageFormat.format( |
| | | "# Error\nSorry, no valid **branch** specified in this url: {0}!", |
| | | path); |
| | | error(response, mkd); |
| | | } else { |
| | | // redirect to default branch |
| | | String base = request.getRequestURI(); |
| | | String url = base + branch + "/"; |
| | | response.sendRedirect(url); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | // identify the requested path |
| | | String requestedPath = getPath(repository, branch, request); |
| | | |
| | | // identify the commit |
| | | RevCommit commit = JGitUtils.getCommit(r, branch); |
| | | if (commit == null) { |
| | | // branch not found! |
| | | String mkd = MessageFormat.format( |
| | | "# Error\nSorry, the repository {0} does not have a **{1}** branch!", |
| | | repository, branch); |
| | | error(response, mkd); |
| | | return; |
| | | } |
| | | |
| | | |
| | | List<PathModel> pathEntries = JGitUtils.getFilesInPath(r, requestedPath, commit); |
| | | if (pathEntries.isEmpty()) { |
| | | // requested a specific resource |
| | | String file = StringUtils.getLastPathElement(requestedPath); |
| | | try { |
| | | // query Tika for the content type |
| | | Tika tika = new Tika(); |
| | | String contentType = tika.detect(file); |
| | | |
| | | if (contentType == null) { |
| | | // ask the container for the content type |
| | | contentType = context.getMimeType(requestedPath); |
| | | |
| | | if (contentType == null) { |
| | | // still unknown content type, assume binary |
| | | contentType = "application/octet-stream"; |
| | | } |
| | | } |
| | | |
| | | setContentType(response, contentType); |
| | | |
| | | if (isTextType(contentType)) { |
| | | |
| | | // load, interpret, and serve text content as UTF-8 |
| | | String [] encodings = runtimeManager.getSettings().getStrings(Keys.web.blobEncodings).toArray(new String[0]); |
| | | String content = JGitUtils.getStringContent(r, commit.getTree(), requestedPath, encodings); |
| | | |
| | | byte [] bytes = content.getBytes(Constants.ENCODING); |
| | | response.setContentLength(bytes.length); |
| | | ByteArrayInputStream is = new ByteArrayInputStream(bytes); |
| | | sendContent(response, JGitUtils.getCommitDate(commit), is); |
| | | |
| | | } else { |
| | | // serve binary content |
| | | String filename = StringUtils.getLastPathElement(requestedPath); |
| | | try { |
| | | String userAgent = request.getHeader("User-Agent"); |
| | | if (userAgent != null && userAgent.indexOf("MSIE 5.5") > -1) { |
| | | response.setHeader("Content-Disposition", "filename=\"" |
| | | + URLEncoder.encode(filename, Constants.ENCODING) + "\""); |
| | | } else if (userAgent != null && userAgent.indexOf("MSIE") > -1) { |
| | | response.setHeader("Content-Disposition", "attachment; filename=\"" |
| | | + URLEncoder.encode(filename, Constants.ENCODING) + "\""); |
| | | } else { |
| | | response.setHeader("Content-Disposition", "attachment; filename=\"" |
| | | + new String(filename.getBytes(Constants.ENCODING), "latin1") + "\""); |
| | | } |
| | | } |
| | | catch (UnsupportedEncodingException e) { |
| | | response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\""); |
| | | } |
| | | |
| | | // stream binary content directly from the repository |
| | | streamFromRepo(response, r, commit, requestedPath); |
| | | } |
| | | return; |
| | | } catch (Exception e) { |
| | | logger.error(null, e); |
| | | } |
| | | } else { |
| | | // path request |
| | | if (!request.getPathInfo().endsWith("/")) { |
| | | // redirect to trailing '/' url |
| | | response.sendRedirect(request.getServletPath() + request.getPathInfo() + "/"); |
| | | return; |
| | | } |
| | | |
| | | if (renderIndex()) { |
| | | // locate and render an index file |
| | | Map<String, String> names = new TreeMap<String, String>(); |
| | | for (PathModel entry : pathEntries) { |
| | | names.put(entry.name.toLowerCase(), entry.name); |
| | | } |
| | | |
| | | List<String> extensions = new ArrayList<String>(); |
| | | extensions.add("html"); |
| | | extensions.add("htm"); |
| | | |
| | | String content = null; |
| | | for (String ext : extensions) { |
| | | String key = "index." + ext; |
| | | |
| | | if (names.containsKey(key)) { |
| | | String fileName = names.get(key); |
| | | String fullPath = fileName; |
| | | if (!requestedPath.isEmpty()) { |
| | | fullPath = requestedPath + "/" + fileName; |
| | | } |
| | | |
| | | String [] encodings = runtimeManager.getSettings().getStrings(Keys.web.blobEncodings).toArray(new String[0]); |
| | | String stringContent = JGitUtils.getStringContent(r, commit.getTree(), fullPath, encodings); |
| | | if (stringContent == null) { |
| | | continue; |
| | | } |
| | | content = stringContent; |
| | | requestedPath = fullPath; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | response.setContentType("text/html; charset=" + Constants.ENCODING); |
| | | byte [] bytes = content.getBytes(Constants.ENCODING); |
| | | response.setContentLength(bytes.length); |
| | | |
| | | ByteArrayInputStream is = new ByteArrayInputStream(bytes); |
| | | sendContent(response, JGitUtils.getCommitDate(commit), is); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // no content, document list or 404 page |
| | | if (pathEntries.isEmpty()) { |
| | | // default 404 page |
| | | String str = MessageFormat.format( |
| | | "# Error\nSorry, the requested resource **{0}** was not found.", |
| | | requestedPath); |
| | | response.setStatus(HttpServletResponse.SC_NOT_FOUND); |
| | | error(response, str); |
| | | return; |
| | | } else { |
| | | // |
| | | // directory list |
| | | // |
| | | response.setContentType("text/html"); |
| | | response.getWriter().append("<style>table th, table td { min-width: 150px; text-align: left; }</style>"); |
| | | response.getWriter().append("<table>"); |
| | | response.getWriter().append("<thead><tr><th>path</th><th>mode</th><th>size</th></tr>"); |
| | | response.getWriter().append("</thead>"); |
| | | response.getWriter().append("<tbody>"); |
| | | String pattern = "<tr><td><a href=\"{0}/{1}\">{1}</a></td><td>{2}</td><td>{3}</td></tr>"; |
| | | final ByteFormat byteFormat = new ByteFormat(); |
| | | if (!pathEntries.isEmpty()) { |
| | | if (pathEntries.get(0).path.indexOf('/') > -1) { |
| | | // we are in a subdirectory, add parent directory link |
| | | String pp = URLEncoder.encode(requestedPath, Constants.ENCODING); |
| | | pathEntries.add(0, new PathModel("..", pp + "/..", 0, FileMode.TREE.getBits(), null, null)); |
| | | } |
| | | } |
| | | |
| | | String basePath = request.getServletPath() + request.getPathInfo(); |
| | | if (basePath.charAt(basePath.length() - 1) == '/') { |
| | | // strip trailing slash |
| | | basePath = basePath.substring(0, basePath.length() - 1); |
| | | } |
| | | for (PathModel entry : pathEntries) { |
| | | String pp = URLEncoder.encode(entry.name, Constants.ENCODING); |
| | | response.getWriter().append(MessageFormat.format(pattern, basePath, pp, |
| | | JGitUtils.getPermissionsFromMode(entry.mode), |
| | | entry.isFile() ? byteFormat.format(entry.size) : "")); |
| | | } |
| | | response.getWriter().append("</tbody>"); |
| | | response.getWriter().append("</table>"); |
| | | } |
| | | } catch (Throwable t) { |
| | | logger.error("Failed to write page to client", t); |
| | | } finally { |
| | | r.close(); |
| | | } |
| | | } |
| | | |
| | | protected boolean isTextType(String contentType) { |
| | | if (contentType.startsWith("text/") |
| | | || "application/json".equals(contentType) |
| | | || "application/xml".equals(contentType)) { |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Override all text types to be plain text. |
| | | * |
| | | * @param response |
| | | * @param contentType |
| | | */ |
| | | protected void setContentType(HttpServletResponse response, String contentType) { |
| | | if (isTextType(contentType)) { |
| | | response.setContentType("text/plain"); |
| | | } else { |
| | | response.setContentType(contentType); |
| | | } |
| | | } |
| | | |
| | | private void streamFromRepo(HttpServletResponse response, Repository repository, |
| | | RevCommit commit, String requestedPath) throws IOException { |
| | | |
| | | response.setDateHeader("Last-Modified", JGitUtils.getCommitDate(commit).getTime()); |
| | | response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate"); |
| | | |
| | | RevWalk rw = new RevWalk(repository); |
| | | TreeWalk tw = new TreeWalk(repository); |
| | | try { |
| | | tw.reset(); |
| | | tw.addTree(commit.getTree()); |
| | | PathFilter f = PathFilter.create(requestedPath); |
| | | tw.setFilter(f); |
| | | tw.setRecursive(true); |
| | | MutableObjectId id = new MutableObjectId(); |
| | | ObjectReader reader = tw.getObjectReader(); |
| | | while (tw.next()) { |
| | | FileMode mode = tw.getFileMode(0); |
| | | if (mode == FileMode.GITLINK || mode == FileMode.TREE) { |
| | | continue; |
| | | } |
| | | tw.getObjectId(id, 0); |
| | | |
| | | long len = reader.getObjectSize(id, org.eclipse.jgit.lib.Constants.OBJ_BLOB); |
| | | response.setIntHeader("Content-Length", (int) len); |
| | | ObjectLoader ldr = repository.open(id); |
| | | ldr.copyTo(response.getOutputStream()); |
| | | } |
| | | } finally { |
| | | tw.release(); |
| | | rw.dispose(); |
| | | } |
| | | |
| | | response.flushBuffer(); |
| | | } |
| | | |
| | | private void sendContent(HttpServletResponse response, Date date, InputStream is) throws ServletException, IOException { |
| | | response.setDateHeader("Last-Modified", date.getTime()); |
| | | response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate"); |
| | | try { |
| | | byte[] tmp = new byte[8192]; |
| | | int len = 0; |
| | | while ((len = is.read(tmp)) > -1) { |
| | | response.getOutputStream().write(tmp, 0, len); |
| | | } |
| | | } finally { |
| | | is.close(); |
| | | } |
| | | response.flushBuffer(); |
| | | } |
| | | |
| | | private void error(HttpServletResponse response, String mkd) throws ServletException, |
| | | IOException, ParseException { |
| | | String content = MarkdownUtils.transformMarkdown(mkd); |
| | | response.setContentType("text/html; charset=" + Constants.ENCODING); |
| | | response.getWriter().write(content); |
| | | } |
| | | |
| | | @Override |
| | | protected void doPost(HttpServletRequest request, HttpServletResponse response) |
| | | throws ServletException, IOException { |
| | | processRequest(request, response); |
| | | } |
| | | |
| | | @Override |
| | | protected void doGet(HttpServletRequest request, HttpServletResponse response) |
| | | throws ServletException, IOException { |
| | | processRequest(request, response); |
| | | } |
| | | } |
| | |
| | | import java.text.MessageFormat;
|
| | |
|
| | | import javax.servlet.FilterChain;
|
| | | import javax.servlet.FilterConfig;
|
| | | import javax.servlet.ServletException;
|
| | | import javax.servlet.ServletRequest;
|
| | | import javax.servlet.ServletResponse;
|
| | |
| | | private IRuntimeManager runtimeManager;
|
| | |
|
| | | @Override
|
| | | protected void inject(ObjectGraph dagger) {
|
| | | super.inject(dagger);
|
| | | protected void inject(ObjectGraph dagger, FilterConfig filterConfig) {
|
| | | super.inject(dagger, filterConfig);
|
| | | this.settings = dagger.get(IStoredSettings.class);
|
| | | this.runtimeManager = dagger.get(IRuntimeManager.class);
|
| | | }
|
| | |
| | | * Handles remote procedure calls.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class RpcServlet extends JsonServlet {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public static final int PROTOCOL_VERSION = 7;
|
| | | public static final int PROTOCOL_VERSION = 8;
|
| | |
|
| | | private IStoredSettings settings;
|
| | |
|
| | |
| | | * @throws java.io.IOException
|
| | | */
|
| | | @Override
|
| | | protected void processRequest(HttpServletRequest request, HttpServletResponse response)
|
| | | throws ServletException, IOException {
|
| | | protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException,
|
| | | IOException {
|
| | | RpcRequest reqType = RpcRequest.fromName(request.getParameter("req"));
|
| | | String objectName = request.getParameter("name");
|
| | | logger.info(MessageFormat.format("Rpc {0} request from {1}", reqType,
|
| | | request.getRemoteAddr()));
|
| | | logger.info(MessageFormat.format("Rpc {0} request from {1}", reqType, request.getRemoteAddr()));
|
| | |
|
| | | UserModel user = (UserModel) request.getUserPrincipal();
|
| | |
|
| | |
| | | }
|
| | | if (model.isCollectingGarbage) {
|
| | | // skip garbage collecting repository
|
| | | logger.warn(MessageFormat.format("Temporarily excluding {0} from RPC, busy collecting garbage", model.name));
|
| | | logger.warn(MessageFormat.format("Temporarily excluding {0} from RPC, busy collecting garbage",
|
| | | model.name));
|
| | | continue;
|
| | | }
|
| | | // get local branches
|
| | |
| | | gitblit.updateRepositoryModel(model.name, model, true);
|
| | | } catch (GitBlitException e) {
|
| | | response.setStatus(failureCode);
|
| | | }
|
| | | } else if (RpcRequest.FORK_REPOSITORY.equals(reqType)) {
|
| | | // fork repository
|
| | | RepositoryModel origin = gitblit.getRepositoryModel(objectName);
|
| | | if (origin == null) {
|
| | | // failed to find repository, error is logged by the repository
|
| | | // manager
|
| | | response.setStatus(failureCode);
|
| | | } else {
|
| | | if (user == null || !user.canFork(origin)) {
|
| | | logger.error("User {} is not permitted to fork '{}'!", user == null ? "anonymous" : user.username,
|
| | | objectName);
|
| | | response.setStatus(failureCode);
|
| | | } else {
|
| | | try {
|
| | | // fork the origin
|
| | | RepositoryModel fork = gitblit.fork(origin, user);
|
| | | if (fork == null) {
|
| | | logger.error("Failed to fork repository '{}'!", objectName);
|
| | | response.setStatus(failureCode);
|
| | | } else {
|
| | | logger.info("User {} has forked '{}'!", user.username, objectName);
|
| | | }
|
| | | } catch (GitBlitException e) {
|
| | | response.setStatus(failureCode);
|
| | | }
|
| | | }
|
| | | }
|
| | | } else if (RpcRequest.EDIT_REPOSITORY.equals(reqType)) {
|
| | | // edit repository
|
| | |
| | | } else if (RpcRequest.SET_REPOSITORY_MEMBER_PERMISSIONS.equals(reqType)) {
|
| | | // set the repository permissions for the specified users
|
| | | RepositoryModel model = gitblit.getRepositoryModel(objectName);
|
| | | Collection<RegistrantAccessPermission> permissions = deserialize(request, response, RpcUtils.REGISTRANT_PERMISSIONS_TYPE);
|
| | | Collection<RegistrantAccessPermission> permissions = deserialize(request, response,
|
| | | RpcUtils.REGISTRANT_PERMISSIONS_TYPE);
|
| | | result = gitblit.setUserAccessPermissions(model, permissions);
|
| | | } else if (RpcRequest.LIST_REPOSITORY_TEAMS.equals(reqType)) {
|
| | | // get repository teams
|
| | |
| | | } else if (RpcRequest.SET_REPOSITORY_TEAM_PERMISSIONS.equals(reqType)) {
|
| | | // set the repository permissions for the specified teams
|
| | | RepositoryModel model = gitblit.getRepositoryModel(objectName);
|
| | | Collection<RegistrantAccessPermission> permissions = deserialize(request, response, RpcUtils.REGISTRANT_PERMISSIONS_TYPE);
|
| | | Collection<RegistrantAccessPermission> permissions = deserialize(request, response,
|
| | | RpcUtils.REGISTRANT_PERMISSIONS_TYPE);
|
| | | result = gitblit.setTeamAccessPermissions(model, permissions);
|
| | | } else if (RpcRequest.LIST_FEDERATION_REGISTRATIONS.equals(reqType)) {
|
| | | // return the list of federation registrations
|
| | |
| | | } else if (RpcRequest.EDIT_SETTINGS.equals(reqType)) {
|
| | | // update settings on the server
|
| | | if (allowAdmin) {
|
| | | Map<String, String> map = deserialize(request, response,
|
| | | RpcUtils.SETTINGS_TYPE);
|
| | | Map<String, String> map = deserialize(request, response, RpcUtils.SETTINGS_TYPE);
|
| | | gitblit.updateSettings(map);
|
| | | } else {
|
| | | response.sendError(notAllowedCode);
|
| | |
| | | import java.text.MessageFormat;
|
| | |
|
| | | import javax.servlet.FilterChain;
|
| | | import javax.servlet.FilterConfig;
|
| | | import javax.servlet.ServletException;
|
| | | import javax.servlet.ServletRequest;
|
| | | import javax.servlet.ServletResponse;
|
| | |
| | | private IProjectManager projectManager;
|
| | |
|
| | | @Override
|
| | | protected void inject(ObjectGraph dagger) {
|
| | | super.inject(dagger);
|
| | | protected void inject(ObjectGraph dagger, FilterConfig filterConfig) {
|
| | | super.inject(dagger, filterConfig);
|
| | | this.runtimeManager = dagger.get(IRuntimeManager.class);
|
| | | this.repositoryManager = dagger.get(IRepositoryManager.class);
|
| | | this.projectManager = dagger.get(IProjectManager.class);
|
| | |
| | | searchType = type;
|
| | | }
|
| | | }
|
| | |
|
| | | Constants.FeedObjectType objectType = Constants.FeedObjectType.COMMIT;
|
| | | if (!StringUtils.isEmpty(request.getParameter("ot"))) {
|
| | | Constants.FeedObjectType type = Constants.FeedObjectType.forName(request.getParameter("ot"));
|
| | | if (type != null) {
|
| | | objectType = type;
|
| | | }
|
| | | }
|
| | |
|
| | | int length = settings.getInteger(Keys.web.syndicationEntries, 25);
|
| | | if (StringUtils.isEmpty(objectId)) {
|
| | | objectId = org.eclipse.jgit.lib.Constants.HEAD;
|
| | |
| | |
|
| | |
|
| | | boolean mountParameters = settings.getBoolean(Keys.web.mountParameters, true);
|
| | | String urlPattern;
|
| | | if (mountParameters) {
|
| | | // mounted parameters
|
| | | urlPattern = "{0}/commit/{1}/{2}";
|
| | | } else {
|
| | | // parameterized parameters
|
| | | urlPattern = "{0}/commit/?r={1}&h={2}";
|
| | | }
|
| | |
|
| | | String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null);
|
| | | if (StringUtils.isEmpty(gitblitUrl)) {
|
| | | gitblitUrl = HttpUtils.getGitblitURL(request);
|
| | |
| | | feedDescription = model.description;
|
| | | }
|
| | |
|
| | | List<RevCommit> commits;
|
| | | if (StringUtils.isEmpty(searchString)) {
|
| | | // standard log/history lookup
|
| | | commits = JGitUtils.getRevLog(repository, objectId, offset, length);
|
| | | if (objectType == Constants.FeedObjectType.TAG) {
|
| | |
|
| | | String urlPattern;
|
| | | if (mountParameters) {
|
| | | // mounted parameters
|
| | | urlPattern = "{0}/tag/{1}/{2}";
|
| | | } else {
|
| | | // parameterized parameters
|
| | | urlPattern = "{0}/tag/?r={1}&h={2}";
|
| | | }
|
| | |
|
| | | List<RefModel> tags = JGitUtils.getTags(repository, false, length, offset);
|
| | |
|
| | | for (RefModel tag : tags) {
|
| | | FeedEntryModel entry = new FeedEntryModel();
|
| | | entry.title = tag.getName();
|
| | | entry.author = tag.getAuthorIdent().getName();
|
| | | entry.link = MessageFormat.format(urlPattern, gitblitUrl,
|
| | | StringUtils.encodeURL(model.name.replace('/', fsc)), tag.getObjectId().getName());
|
| | | entry.published = tag.getDate();
|
| | | entry.contentType = "text/html";
|
| | | entry.content = tag.getFullMessage();
|
| | | entry.repository = model.name;
|
| | | entry.branch = objectId;
|
| | |
|
| | | entry.tags = new ArrayList<String>();
|
| | |
|
| | | // add tag id and referenced commit id
|
| | | entry.tags.add("tag:" + tag.getObjectId().getName());
|
| | | entry.tags.add("commit:" + tag.getReferencedObjectId().getName());
|
| | |
|
| | | entries.add(entry);
|
| | | }
|
| | | } else {
|
| | | // repository search
|
| | | commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType,
|
| | | offset, length);
|
| | | }
|
| | | Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository, model.showRemoteBranches);
|
| | | BugtraqProcessor processor = new BugtraqProcessor(settings);
|
| | |
|
| | | // convert RevCommit to SyndicatedEntryModel
|
| | | for (RevCommit commit : commits) {
|
| | | FeedEntryModel entry = new FeedEntryModel();
|
| | | entry.title = commit.getShortMessage();
|
| | | entry.author = commit.getAuthorIdent().getName();
|
| | | entry.link = MessageFormat.format(urlPattern, gitblitUrl,
|
| | | StringUtils.encodeURL(model.name.replace('/', fsc)), commit.getName());
|
| | | entry.published = commit.getCommitterIdent().getWhen();
|
| | | entry.contentType = "text/html";
|
| | | String message = processor.processCommitMessage(repository, model, commit.getFullMessage());
|
| | | entry.content = message;
|
| | | entry.repository = model.name;
|
| | | entry.branch = objectId;
|
| | | entry.tags = new ArrayList<String>();
|
| | |
|
| | | // add commit id and parent commit ids
|
| | | entry.tags.add("commit:" + commit.getName());
|
| | | for (RevCommit parent : commit.getParents()) {
|
| | | entry.tags.add("parent:" + parent.getName());
|
| | | String urlPattern;
|
| | | if (mountParameters) {
|
| | | // mounted parameters
|
| | | urlPattern = "{0}/commit/{1}/{2}";
|
| | | } else {
|
| | | // parameterized parameters
|
| | | urlPattern = "{0}/commit/?r={1}&h={2}";
|
| | | }
|
| | |
|
| | | // add refs to tabs list
|
| | | List<RefModel> refs = allRefs.get(commit.getId());
|
| | | if (refs != null && refs.size() > 0) {
|
| | | for (RefModel ref : refs) {
|
| | | entry.tags.add("ref:" + ref.getName());
|
| | | List<RevCommit> commits;
|
| | | if (StringUtils.isEmpty(searchString)) {
|
| | | // standard log/history lookup
|
| | | commits = JGitUtils.getRevLog(repository, objectId, offset, length);
|
| | | } else {
|
| | | // repository search
|
| | | commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType,
|
| | | offset, length);
|
| | | }
|
| | | Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository, model.showRemoteBranches);
|
| | | BugtraqProcessor processor = new BugtraqProcessor(settings);
|
| | |
|
| | | // convert RevCommit to SyndicatedEntryModel
|
| | | for (RevCommit commit : commits) {
|
| | | FeedEntryModel entry = new FeedEntryModel();
|
| | | entry.title = commit.getShortMessage();
|
| | | entry.author = commit.getAuthorIdent().getName();
|
| | | entry.link = MessageFormat.format(urlPattern, gitblitUrl,
|
| | | StringUtils.encodeURL(model.name.replace('/', fsc)), commit.getName());
|
| | | entry.published = commit.getCommitterIdent().getWhen();
|
| | | entry.contentType = "text/html";
|
| | | String message = processor.processCommitMessage(repository, model, commit.getFullMessage());
|
| | | entry.content = message;
|
| | | entry.repository = model.name;
|
| | | entry.branch = objectId;
|
| | | entry.tags = new ArrayList<String>();
|
| | |
|
| | | // add commit id and parent commit ids
|
| | | entry.tags.add("commit:" + commit.getName());
|
| | | for (RevCommit parent : commit.getParents()) {
|
| | | entry.tags.add("parent:" + parent.getName());
|
| | | }
|
| | |
|
| | | // add refs to tabs list
|
| | | List<RefModel> refs = allRefs.get(commit.getId());
|
| | | if (refs != null && refs.size() > 0) {
|
| | | for (RefModel ref : refs) {
|
| | | entry.tags.add("ref:" + ref.getName());
|
| | | }
|
| | | }
|
| | | entries.add(entry);
|
| | | }
|
| | | entries.add(entry);
|
| | | }
|
| | | }
|
| | |
|
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns the assigned ticket ids. |
| | | * |
| | | * @return the assigned ticket ids |
| | | */ |
| | | @Override |
| | | public synchronized Set<Long> getIds(RepositoryModel repository) { |
| | | Repository db = repositoryManager.getRepository(repository.name); |
| | | try { |
| | | if (getTicketsBranch(db) == null) { |
| | | return Collections.emptySet(); |
| | | } |
| | | Set<Long> ids = new TreeSet<Long>(); |
| | | List<PathModel> paths = JGitUtils.getDocuments(db, Arrays.asList("json"), BRANCH); |
| | | for (PathModel path : paths) { |
| | | String name = path.name.substring(path.name.lastIndexOf('/') + 1); |
| | | if (!JOURNAL.equals(name)) { |
| | | continue; |
| | | } |
| | | String tid = path.path.split("/")[2]; |
| | | long ticketId = Long.parseLong(tid); |
| | | ids.add(ticketId); |
| | | } |
| | | return ids; |
| | | } finally { |
| | | if (db != null) { |
| | | db.close(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Assigns a new ticket id. |
| | | * |
| | | * @param repository |
| | |
| | | } |
| | | AtomicLong lastId = lastAssignedId.get(repository.name); |
| | | if (lastId.get() <= 0) { |
| | | List<PathModel> paths = JGitUtils.getDocuments(db, Arrays.asList("json"), BRANCH); |
| | | for (PathModel path : paths) { |
| | | String name = path.name.substring(path.name.lastIndexOf('/') + 1); |
| | | if (!JOURNAL.equals(name)) { |
| | | continue; |
| | | } |
| | | String tid = path.path.split("/")[2]; |
| | | long ticketId = Long.parseLong(tid); |
| | | if (ticketId > lastId.get()) { |
| | | lastId.set(ticketId); |
| | | Set<Long> ids = getIds(repository); |
| | | for (long id : ids) { |
| | | if (id > lastId.get()) { |
| | | lastId.set(id); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the journal for the ticket. |
| | | * |
| | | * @param repository |
| | | * @param ticketId |
| | | * @return a journal, if it exists, otherwise null |
| | | */ |
| | | @Override |
| | | protected List<Change> getJournalImpl(RepositoryModel repository, long ticketId) { |
| | | Repository db = repositoryManager.getRepository(repository.name); |
| | | try { |
| | | List<Change> changes = getJournal(db, ticketId); |
| | | if (ArrayUtils.isEmpty(changes)) { |
| | | log.warn("Empty journal for {}:{}", repository, ticketId); |
| | | return null; |
| | | } |
| | | return changes; |
| | | } finally { |
| | | db.close(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns the journal for the specified ticket. |
| | | * |
| | | * @param db |
| | |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.TreeSet; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.atomic.AtomicLong; |
| | | |
| | |
| | | return hasTicket; |
| | | } |
| | | |
| | | @Override |
| | | public synchronized Set<Long> getIds(RepositoryModel repository) { |
| | | Set<Long> ids = new TreeSet<Long>(); |
| | | Repository db = repositoryManager.getRepository(repository.name); |
| | | try { |
| | | // identify current highest ticket id by scanning the paths in the tip tree |
| | | File dir = new File(db.getDirectory(), TICKETS_PATH); |
| | | dir.mkdirs(); |
| | | List<File> journals = findAll(dir, JOURNAL); |
| | | for (File journal : journals) { |
| | | // Reconstruct ticketId from the path |
| | | // id/26/326/journal.json |
| | | String path = FileUtils.getRelativePath(dir, journal); |
| | | String tid = path.split("/")[1]; |
| | | long ticketId = Long.parseLong(tid); |
| | | ids.add(ticketId); |
| | | } |
| | | } finally { |
| | | if (db != null) { |
| | | db.close(); |
| | | } |
| | | } |
| | | return ids; |
| | | } |
| | | |
| | | /** |
| | | * Assigns a new ticket id. |
| | | * |
| | |
| | | } |
| | | AtomicLong lastId = lastAssignedId.get(repository.name); |
| | | if (lastId.get() <= 0) { |
| | | // identify current highest ticket id by scanning the paths in the tip tree |
| | | File dir = new File(db.getDirectory(), TICKETS_PATH); |
| | | dir.mkdirs(); |
| | | List<File> journals = findAll(dir, JOURNAL); |
| | | for (File journal : journals) { |
| | | // Reconstruct ticketId from the path |
| | | // id/26/326/journal.json |
| | | String path = FileUtils.getRelativePath(dir, journal); |
| | | String tid = path.split("/")[1]; |
| | | long ticketId = Long.parseLong(tid); |
| | | if (ticketId > lastId.get()) { |
| | | lastId.set(ticketId); |
| | | Set<Long> ids = getIds(repository); |
| | | for (long id : ids) { |
| | | if (id > lastId.get()) { |
| | | lastId.set(id); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the ticket from the repository by first looking-up the changeId |
| | | * associated with the ticketId. |
| | | * Retrieves the ticket from the repository. |
| | | * |
| | | * @param repository |
| | | * @param ticketId |
| | |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the journal for the ticket. |
| | | * |
| | | * @param repository |
| | | * @param ticketId |
| | | * @return a journal, if it exists, otherwise null |
| | | */ |
| | | @Override |
| | | protected List<Change> getJournalImpl(RepositoryModel repository, long ticketId) { |
| | | Repository db = repositoryManager.getRepository(repository.name); |
| | | try { |
| | | List<Change> changes = getJournal(db, ticketId); |
| | | if (ArrayUtils.isEmpty(changes)) { |
| | | log.warn("Empty journal for {}:{}", repository, ticketId); |
| | | return null; |
| | | } |
| | | return changes; |
| | | } finally { |
| | | db.close(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns the journal for the specified ticket. |
| | | * |
| | | * @param db |
| | |
| | | import com.gitblit.models.TicketModel.Patchset; |
| | | import com.gitblit.models.TicketModel.Status; |
| | | import com.gitblit.tickets.TicketIndexer.Lucene; |
| | | import com.gitblit.utils.DeepCopier; |
| | | import com.gitblit.utils.DiffUtils; |
| | | import com.gitblit.utils.DiffUtils.DiffStat; |
| | | import com.gitblit.utils.StringUtils; |
| | |
| | | * |
| | | */ |
| | | public abstract class ITicketService { |
| | | |
| | | public static final String SETTING_UPDATE_DIFFSTATS = "migration.updateDiffstats"; |
| | | |
| | | private static final String LABEL = "label"; |
| | | |
| | |
| | | private final Map<String, List<TicketLabel>> labelsCache; |
| | | |
| | | private final Map<String, List<TicketMilestone>> milestonesCache; |
| | | |
| | | private final boolean updateDiffstats; |
| | | |
| | | private static class TicketKey { |
| | | final String repository; |
| | |
| | | |
| | | this.labelsCache = new ConcurrentHashMap<String, List<TicketLabel>>(); |
| | | this.milestonesCache = new ConcurrentHashMap<String, List<TicketMilestone>>(); |
| | | |
| | | this.updateDiffstats = settings.getBoolean(SETTING_UPDATE_DIFFSTATS, true); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public boolean isAcceptingTicketUpdates(RepositoryModel repository) { |
| | | return isReady() |
| | | && repository.hasCommits |
| | | && repository.isBare |
| | | && !repository.isFrozen |
| | | && !repository.isMirror; |
| | |
| | | public TicketMilestone getMilestone(RepositoryModel repository, String milestone) { |
| | | for (TicketMilestone ms : getMilestones(repository)) { |
| | | if (ms.name.equalsIgnoreCase(milestone)) { |
| | | TicketMilestone tm = DeepCopier.copy(ms); |
| | | String q = QueryBuilder.q(Lucene.rid.matches(repository.getRID())).and(Lucene.milestone.matches(milestone)).build(); |
| | | ms.tickets = indexer.queryFor(q, 1, 0, Lucene.number.name(), true); |
| | | return ms; |
| | | tm.tickets = indexer.queryFor(q, 1, 0, Lucene.number.name(), true); |
| | | return tm; |
| | | } |
| | | } |
| | | return null; |
| | |
| | | * @since 1.4.0 |
| | | */ |
| | | public synchronized boolean renameMilestone(RepositoryModel repository, String oldName, String newName, String createdBy) { |
| | | return renameMilestone(repository, oldName, newName, createdBy, true); |
| | | } |
| | | |
| | | /** |
| | | * Renames a milestone. |
| | | * |
| | | * @param repository |
| | | * @param oldName |
| | | * @param newName |
| | | * @param createdBy |
| | | * @param notifyOpenTickets |
| | | * @return true if successful |
| | | * @since 1.6.0 |
| | | */ |
| | | public synchronized boolean renameMilestone(RepositoryModel repository, String oldName, |
| | | String newName, String createdBy, boolean notifyOpenTickets) { |
| | | if (StringUtils.isEmpty(newName)) { |
| | | throw new IllegalArgumentException("new milestone can not be empty!"); |
| | | } |
| | |
| | | config.setString(MILESTONE, newName, STATUS, milestone.status.name()); |
| | | config.setString(MILESTONE, newName, COLOR, milestone.color); |
| | | if (milestone.due != null) { |
| | | config.setString(MILESTONE, milestone.name, DUE, |
| | | config.setString(MILESTONE, newName, DUE, |
| | | new SimpleDateFormat(DUE_DATE_PATTERN).format(milestone.due)); |
| | | } |
| | | config.save(); |
| | |
| | | Change change = new Change(createdBy); |
| | | change.setField(Field.milestone, newName); |
| | | TicketModel ticket = updateTicket(repository, qr.number, change); |
| | | notifier.queueMailing(ticket); |
| | | if (notifyOpenTickets && ticket.isOpen()) { |
| | | notifier.queueMailing(ticket); |
| | | } |
| | | } |
| | | notifier.sendAll(); |
| | | if (notifyOpenTickets) { |
| | | notifier.sendAll(); |
| | | } |
| | | |
| | | return true; |
| | | } catch (IOException e) { |
| | |
| | | * @since 1.4.0 |
| | | */ |
| | | public synchronized boolean deleteMilestone(RepositoryModel repository, String milestone, String createdBy) { |
| | | return deleteMilestone(repository, milestone, createdBy, true); |
| | | } |
| | | |
| | | /** |
| | | * Deletes a milestone. |
| | | * |
| | | * @param repository |
| | | * @param milestone |
| | | * @param createdBy |
| | | * @param notifyOpenTickets |
| | | * @return true if successful |
| | | * @since 1.6.0 |
| | | */ |
| | | public synchronized boolean deleteMilestone(RepositoryModel repository, String milestone, |
| | | String createdBy, boolean notifyOpenTickets) { |
| | | if (StringUtils.isEmpty(milestone)) { |
| | | throw new IllegalArgumentException("milestone can not be empty!"); |
| | | } |
| | | Repository db = null; |
| | | try { |
| | | TicketMilestone tm = getMilestone(repository, milestone); |
| | | db = repositoryManager.getRepository(repository.name); |
| | | StoredConfig config = db.getConfig(); |
| | | config.unsetSection(MILESTONE, milestone); |
| | |
| | | |
| | | milestonesCache.remove(repository.name); |
| | | |
| | | TicketNotifier notifier = createNotifier(); |
| | | for (QueryResult qr : tm.tickets) { |
| | | Change change = new Change(createdBy); |
| | | change.setField(Field.milestone, ""); |
| | | TicketModel ticket = updateTicket(repository, qr.number, change); |
| | | if (notifyOpenTickets && ticket.isOpen()) { |
| | | notifier.queueMailing(ticket); |
| | | } |
| | | } |
| | | if (notifyOpenTickets) { |
| | | notifier.sendAll(); |
| | | } |
| | | return true; |
| | | } catch (IOException e) { |
| | | log.error("failed to delete milestone " + milestone + " in " + repository, e); |
| | |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Returns the set of assigned ticket ids in the repository. |
| | | * |
| | | * @param repository |
| | | * @return a set of assigned ticket ids in the repository |
| | | * @since 1.6.0 |
| | | */ |
| | | public abstract Set<Long> getIds(RepositoryModel repository); |
| | | |
| | | /** |
| | | * Assigns a new ticket id. |
| | |
| | | ticket = getTicketImpl(repository, ticketId); |
| | | // if ticket exists |
| | | if (ticket != null) { |
| | | if (ticket.hasPatchsets()) { |
| | | if (ticket.hasPatchsets() && updateDiffstats) { |
| | | Repository r = repositoryManager.getRepository(repository.name); |
| | | try { |
| | | Patchset patchset = ticket.getCurrentPatchset(); |
| | |
| | | */ |
| | | protected abstract TicketModel getTicketImpl(RepositoryModel repository, long ticketId); |
| | | |
| | | |
| | | /** |
| | | * Returns the journal used to build a ticket. |
| | | * |
| | | * @param repository |
| | | * @param ticketId |
| | | * @return the journal for the ticket, if it exists, otherwise null |
| | | * @since 1.6.0 |
| | | */ |
| | | public final List<Change> getJournal(RepositoryModel repository, long ticketId) { |
| | | if (hasTicket(repository, ticketId)) { |
| | | List<Change> journal = getJournalImpl(repository, ticketId); |
| | | return journal; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the ticket journal. |
| | | * |
| | | * @param repository |
| | | * @param ticketId |
| | | * @return a ticket, if it exists, otherwise null |
| | | * @since 1.6.0 |
| | | */ |
| | | protected abstract List<Change> getJournalImpl(RepositoryModel repository, long ticketId); |
| | | |
| | | /** |
| | | * Get the ticket url |
| | | * |
| | |
| | | |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | import com.gitblit.manager.INotificationManager; |
| | | import com.gitblit.manager.IPluginManager; |
| | |
| | | } |
| | | |
| | | @Override |
| | | public synchronized Set<Long> getIds(RepositoryModel repository) { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | @Override |
| | | public synchronized long assignNewId(RepositoryModel repository) { |
| | | return 0L; |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | protected List<Change> getJournalImpl(RepositoryModel repository, long ticketId) { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public boolean supportsAttachments() { |
| | | return false; |
| | | } |
| | |
| | | return type != null && Type.Proposal == type; |
| | | } |
| | | |
| | | public boolean isOpen() { |
| | | return !status.isClosed(); |
| | | } |
| | | |
| | | public boolean isClosed() { |
| | | return status.isClosed(); |
| | | } |
| | | |
| | | public boolean isMerged() { |
| | | return Status.Merged == status && !StringUtils.isEmpty(mergeSha); |
| | | } |
| | |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.TreeSet; |
| | | |
| | | import org.apache.commons.pool2.impl.GenericObjectPoolConfig; |
| | | |
| | |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public Set<Long> getIds(RepositoryModel repository) { |
| | | Set<Long> ids = new TreeSet<Long>(); |
| | | Jedis jedis = pool.getResource(); |
| | | try {// account for migrated tickets |
| | | Set<String> keys = jedis.keys(key(repository, KeyType.journal, "*")); |
| | | for (String tkey : keys) { |
| | | // {repo}:journal:{id} |
| | | String id = tkey.split(":")[2]; |
| | | long ticketId = Long.parseLong(id); |
| | | ids.add(ticketId); |
| | | } |
| | | } catch (JedisException e) { |
| | | log.error("failed to assign new ticket id in Redis @ " + getUrl(), e); |
| | | pool.returnBrokenResource(jedis); |
| | | jedis = null; |
| | | } finally { |
| | | if (jedis != null) { |
| | | pool.returnResource(jedis); |
| | | } |
| | | } |
| | | return ids; |
| | | } |
| | | |
| | | /** |
| | | * Assigns a new ticket id. |
| | | * |
| | |
| | | String key = key(repository, KeyType.counter, null); |
| | | String val = jedis.get(key); |
| | | if (isNull(val)) { |
| | | jedis.set(key, "0"); |
| | | long lastId = 0; |
| | | Set<Long> ids = getIds(repository); |
| | | for (long id : ids) { |
| | | if (id > lastId) { |
| | | lastId = id; |
| | | } |
| | | } |
| | | jedis.set(key, "" + lastId); |
| | | } |
| | | long ticketNumber = jedis.incr(key); |
| | | return ticketNumber; |
| | |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the ticket from the repository by first looking-up the changeId |
| | | * associated with the ticketId. |
| | | * Retrieves the ticket from the repository. |
| | | * |
| | | * @param repository |
| | | * @param ticketId |
| | |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the journal for the ticket. |
| | | * |
| | | * @param repository |
| | | * @param ticketId |
| | | * @return a journal, if it exists, otherwise null |
| | | */ |
| | | @Override |
| | | protected List<Change> getJournalImpl(RepositoryModel repository, long ticketId) { |
| | | Jedis jedis = pool.getResource(); |
| | | if (jedis == null) { |
| | | return null; |
| | | } |
| | | |
| | | try { |
| | | List<Change> changes = getJournal(jedis, repository, ticketId); |
| | | if (ArrayUtils.isEmpty(changes)) { |
| | | log.warn("Empty journal for {}:{}", repository, ticketId); |
| | | return null; |
| | | } |
| | | return changes; |
| | | } catch (JedisException e) { |
| | | log.error("failed to retrieve journal from Redis @ " + getUrl(), e); |
| | | pool.returnBrokenResource(jedis); |
| | | jedis = null; |
| | | } finally { |
| | | if (jedis != null) { |
| | | pool.returnResource(jedis); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * Returns the journal for the specified ticket. |
| | | * |
| | | * @param repository |
| | |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public final String name; |
| | | public String name; |
| | | |
| | | public String color; |
| | | |
| | | public List<QueryResult> tickets; |
| | | |
| | | |
| | | public TicketLabel(String name) { |
| | | setName(name); |
| | | } |
| | | |
| | | public void setName(String name) { |
| | | this.name = name; |
| | | this.color = StringUtils.getColor(name); |
| | | } |
| | |
| | | status = Status.Open; |
| | | } |
| | | |
| | | public boolean isOpen() { |
| | | return status == Status.Open; |
| | | } |
| | | |
| | | public boolean isOverdue() { |
| | | return due == null ? false : System.currentTimeMillis() > due.getTime(); |
| | | } |
| | | |
| | | public void setDue(Date due) { |
| | | this.due = due; |
| | | } |
| | | |
| | | public int getProgress() { |
| | | int total = getTotalTickets(); |
| | | if (total == 0) { |
| | |
| | | } |
| | | } |
| | | } |
| | | mailing.setRecipients(toAddresses); |
| | | |
| | | // |
| | | // CC recipients |
| | |
| | | |
| | | // repository owners |
| | | if (!ArrayUtils.isEmpty(repository.owners)) { |
| | | tos.addAll(repository.owners); |
| | | ccs.addAll(repository.owners); |
| | | } |
| | | |
| | | // cc users mentioned in last comment |
| | |
| | | } |
| | | ccAddresses.addAll(settings.getStrings(Keys.mail.mailingLists)); |
| | | |
| | | // respect the author's email preference |
| | | UserModel lastAuthor = userManager.getUserModel(lastChange.author); |
| | | if (!lastAuthor.getPreferences().isEmailMeOnMyTicketChanges()) { |
| | | toAddresses.remove(lastAuthor.emailAddress); |
| | | ccAddresses.remove(lastAuthor.emailAddress); |
| | | } |
| | | |
| | | mailing.setRecipients(toAddresses); |
| | | mailing.setCCs(ccAddresses); |
| | | } |
| | | |
| | |
| | | |
| | | To review a rewritten patchset |
| | | |
| | | git fetch origin && git checkout ${ticketBranch} && git reset --hard origin/${ticketBranch} |
| | | git fetch origin && git checkout -B ${ticketBranch} |
| | | |
| | | |
| | |
| | | public String formatUrl(String gituser, String servername, String repository) { |
| | | if (sshd.getPort() == DEFAULT_PORT) { |
| | | // standard port |
| | | return MessageFormat.format("{0}@{1}/{2}", gituser, servername, |
| | | return MessageFormat.format("ssh://{0}@{1}/{2}", gituser, servername, |
| | | repository); |
| | | } else { |
| | | // non-standard port |
| | |
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the list of tags in the repository. If repository does not exist
|
| | | * or is empty, an empty list is returned.
|
| | | *
|
| | | * @param repository
|
| | | * @param fullName
|
| | | * if true, /refs/tags/yadayadayada is returned. If false,
|
| | | * yadayadayada is returned.
|
| | | * @param maxCount
|
| | | * if < 0, all tags are returned
|
| | | * @param offset
|
| | | * if maxCount provided sets the starting point of the records to return
|
| | | * @return list of tags
|
| | | */
|
| | | public static List<RefModel> getTags(Repository repository, boolean fullName, int maxCount, int offset) {
|
| | | return getRefs(repository, Constants.R_TAGS, fullName, maxCount, offset);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the list of local branches in the repository. If repository does
|
| | | * not exist or is empty, an empty list is returned.
|
| | | *
|
| | |
| | | */
|
| | | private static List<RefModel> getRefs(Repository repository, String refs, boolean fullName,
|
| | | int maxCount) {
|
| | | return getRefs(repository, refs, fullName, maxCount, 0);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns a list of references in the repository matching "refs". If the
|
| | | * repository is null or empty, an empty list is returned.
|
| | | *
|
| | | * @param repository
|
| | | * @param refs
|
| | | * if unspecified, all refs are returned
|
| | | * @param fullName
|
| | | * if true, /refs/something/yadayadayada is returned. If false,
|
| | | * yadayadayada is returned.
|
| | | * @param maxCount
|
| | | * if < 0, all references are returned
|
| | | * @param offset
|
| | | * if maxCount provided sets the starting point of the records to return
|
| | | * @return list of references
|
| | | */
|
| | | private static List<RefModel> getRefs(Repository repository, String refs, boolean fullName,
|
| | | int maxCount, int offset) {
|
| | | List<RefModel> list = new ArrayList<RefModel>();
|
| | | if (maxCount == 0) {
|
| | | return list;
|
| | |
| | | Collections.sort(list);
|
| | | Collections.reverse(list);
|
| | | if (maxCount > 0 && list.size() > maxCount) {
|
| | | list = new ArrayList<RefModel>(list.subList(0, maxCount));
|
| | | if (offset < 0) {
|
| | | offset = 0;
|
| | | }
|
| | | int endIndex = offset + maxCount;
|
| | | if (endIndex > list.size()) {
|
| | | endIndex = list.size();
|
| | | }
|
| | | list = new ArrayList<RefModel>(list.subList(offset, endIndex));
|
| | | }
|
| | | } catch (IOException e) {
|
| | | error(e, repository, "{0} failed to retrieve {1}", refs);
|
| | |
| | | String canonicalUrl = settings.getString(Keys.web.canonicalUrl, "https://localhost:8443");
|
| | |
|
| | | // emphasize and link mentions
|
| | | String mentionReplacement = String.format(" **<a href=\"%1s/user/$1\">@$1</a>**", canonicalUrl);
|
| | | String mentionReplacement = String.format(" **[@$1](%1s/user/$1)**", canonicalUrl);
|
| | | text = text.replaceAll("\\s@([A-Za-z0-9-_]+)", mentionReplacement);
|
| | |
|
| | | // link ticket refs |
| | |
| | | // link commit shas
|
| | | int shaLen = settings.getInteger(Keys.web.shortCommitIdLength, 6);
|
| | | String commitPattern = MessageFormat.format("\\s([A-Fa-f0-9]'{'{0}'}')([A-Fa-f0-9]'{'{1}'}')", shaLen, 40 - shaLen);
|
| | | String commitReplacement = String.format(" <a class='commit' href='%1$s/commit?r=%2$s&h=$1$2'>$1</a>", canonicalUrl, repositoryName);
|
| | | String commitReplacement = String.format(" [`$1`](%1$s/commit?r=%2$s&h=$1$2)", canonicalUrl, repositoryName);
|
| | | text = text.replaceAll(commitPattern, commitReplacement);
|
| | |
|
| | | String html = transformMarkdown(text);
|
| | |
| | |
|
| | | }
|
| | |
|
| | | /**
|
| | | /**
|
| | | * Create a fork of a repository.
|
| | | *
|
| | | * @param repository
|
| | |
|
| | | * @return true if the action succeeded
|
| | | * @throws IOException
|
| | | */
|
| | | public static boolean forkRepository(RepositoryModel repository, String serverUrl,
|
| | | String account, char[] password) throws IOException {
|
| | | return doAction(RpcRequest.FORK_REPOSITORY, repository.name, null, serverUrl, account, password);
|
| | | }
|
| | |
|
| | |
|
| | | /**
|
| | | * Send a revised version of the repository model to the Gitblit server.
|
| | | *
|
| | | * @param repository
|
| | |
| | | import java.util.List;
|
| | |
|
| | | import com.gitblit.Constants;
|
| | | import com.gitblit.Constants.FeedObjectType;
|
| | | import com.gitblit.GitBlitException;
|
| | | import com.gitblit.models.FeedEntryModel;
|
| | | import com.sun.syndication.feed.synd.SyndCategory;
|
| | |
| | | */
|
| | | public static List<FeedEntryModel> readFeed(String url, String repository, String branch,
|
| | | int numberOfEntries, int page, String username, char[] password) throws IOException {
|
| | | return readFeed(url, repository, branch, FeedObjectType.COMMIT, numberOfEntries,
|
| | | page, username, password);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Reads tags from the specified repository.
|
| | | *
|
| | | * @param url
|
| | | * the url of the Gitblit server
|
| | | * @param repository
|
| | | * the repository name
|
| | | * @param branch
|
| | | * the branch name (optional)
|
| | | * @param numberOfEntries
|
| | | * the number of entries to retrieve. if <= 0 the server default
|
| | | * is used.
|
| | | * @param page
|
| | | * 0-indexed. used to paginate the results.
|
| | | * @param username
|
| | | * @param password
|
| | | * @return a list of SyndicationModel entries
|
| | | * @throws {@link IOException}
|
| | | */
|
| | | public static List<FeedEntryModel> readTags(String url, String repository,
|
| | | int numberOfEntries, int page, String username, char[] password) throws IOException {
|
| | | return readFeed(url, repository, null, FeedObjectType.TAG, numberOfEntries,
|
| | | page, username, password);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Reads a Gitblit RSS feed.
|
| | | *
|
| | | * @param url
|
| | | * the url of the Gitblit server
|
| | | * @param repository
|
| | | * the repository name
|
| | | * @param branch
|
| | | * the branch name (optional)
|
| | | * @param objectType
|
| | | * the object type to return (optional, COMMIT assummed)
|
| | | * @param numberOfEntries
|
| | | * the number of entries to retrieve. if <= 0 the server default
|
| | | * is used.
|
| | | * @param page
|
| | | * 0-indexed. used to paginate the results.
|
| | | * @param username
|
| | | * @param password
|
| | | * @return a list of SyndicationModel entries
|
| | | * @throws {@link IOException}
|
| | | */
|
| | | private static List<FeedEntryModel> readFeed(String url, String repository, String branch,
|
| | | FeedObjectType objectType, int numberOfEntries, int page, String username,
|
| | | char[] password) throws IOException {
|
| | | // build feed url
|
| | | List<String> parameters = new ArrayList<String>();
|
| | | if (numberOfEntries > 0) {
|
| | |
| | | if (!StringUtils.isEmpty(branch)) {
|
| | | parameters.add("h=" + branch);
|
| | | }
|
| | | if (objectType != null) {
|
| | | parameters.add("ot=" + objectType.name());
|
| | | }
|
| | | return readFeed(url, parameters, repository, branch, username, password);
|
| | | }
|
| | |
|
| | |
| | | import org.apache.wicket.Request; |
| | | import org.apache.wicket.Response; |
| | | import org.apache.wicket.Session; |
| | | import org.apache.wicket.application.IClassResolver; |
| | | import org.apache.wicket.markup.html.WebPage; |
| | | import org.apache.wicket.protocol.http.WebApplication; |
| | | |
| | | import ro.fortsoft.pf4j.PluginState; |
| | | import ro.fortsoft.pf4j.PluginWrapper; |
| | | |
| | | import com.gitblit.IStoredSettings; |
| | | import com.gitblit.Keys; |
| | | import com.gitblit.extensions.GitblitWicketPlugin; |
| | | import com.gitblit.manager.IAuthenticationManager; |
| | | import com.gitblit.manager.IFederationManager; |
| | | import com.gitblit.manager.IGitblit; |
| | |
| | | import com.gitblit.wicket.pages.ComparePage; |
| | | import com.gitblit.wicket.pages.DocPage; |
| | | import com.gitblit.wicket.pages.DocsPage; |
| | | import com.gitblit.wicket.pages.EditMilestonePage; |
| | | import com.gitblit.wicket.pages.EditRepositoryPage; |
| | | import com.gitblit.wicket.pages.EditTicketPage; |
| | | import com.gitblit.wicket.pages.ExportTicketPage; |
| | | import com.gitblit.wicket.pages.FederationRegistrationPage; |
| | |
| | | import com.gitblit.wicket.pages.LuceneSearchPage; |
| | | import com.gitblit.wicket.pages.MetricsPage; |
| | | import com.gitblit.wicket.pages.MyDashboardPage; |
| | | import com.gitblit.wicket.pages.MyTicketsPage; |
| | | import com.gitblit.wicket.pages.NewMilestonePage; |
| | | import com.gitblit.wicket.pages.NewRepositoryPage; |
| | | import com.gitblit.wicket.pages.NewTicketPage; |
| | | import com.gitblit.wicket.pages.OverviewPage; |
| | | import com.gitblit.wicket.pages.PatchPage; |
| | | import com.gitblit.wicket.pages.ProjectPage; |
| | | import com.gitblit.wicket.pages.ProjectsPage; |
| | | import com.gitblit.wicket.pages.RawPage; |
| | | import com.gitblit.wicket.pages.ReflogPage; |
| | | import com.gitblit.wicket.pages.RepositoriesPage; |
| | | import com.gitblit.wicket.pages.ReviewProposalPage; |
| | | import com.gitblit.wicket.pages.SummaryPage; |
| | | import com.gitblit.wicket.pages.TagPage; |
| | | import com.gitblit.wicket.pages.TagsPage; |
| | | import com.gitblit.wicket.pages.TeamsPage; |
| | | import com.gitblit.wicket.pages.TicketsPage; |
| | | import com.gitblit.wicket.pages.TreePage; |
| | | import com.gitblit.wicket.pages.UserPage; |
| | | import com.gitblit.wicket.pages.UsersPage; |
| | | |
| | | public class GitBlitWebApp extends WebApplication { |
| | | public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { |
| | | |
| | | private final Class<? extends WebPage> homePageClass = MyDashboardPage.class; |
| | | |
| | | private final Class<? extends WebPage> newRepositoryPageClass = NewRepositoryPage.class; |
| | | |
| | | private final Map<String, CacheControl> cacheablePages = new HashMap<String, CacheControl>(); |
| | | |
| | |
| | | mount("/tag", TagPage.class, "r", "h"); |
| | | mount("/tree", TreePage.class, "r", "h", "f"); |
| | | mount("/blob", BlobPage.class, "r", "h", "f"); |
| | | mount("/raw", RawPage.class, "r", "h", "f"); |
| | | mount("/blobdiff", BlobDiffPage.class, "r", "h", "f"); |
| | | mount("/commitdiff", CommitDiffPage.class, "r", "h"); |
| | | mount("/compare", ComparePage.class, "r", "h"); |
| | |
| | | mount("/metrics", MetricsPage.class, "r"); |
| | | mount("/blame", BlamePage.class, "r", "h", "f"); |
| | | mount("/users", UsersPage.class); |
| | | mount("/teams", TeamsPage.class); |
| | | mount("/logout", LogoutPage.class); |
| | | |
| | | // setup ticket urls |
| | |
| | | mount("/tickets/new", NewTicketPage.class, "r"); |
| | | mount("/tickets/edit", EditTicketPage.class, "r", "h"); |
| | | mount("/tickets/export", ExportTicketPage.class, "r", "h"); |
| | | mount("/milestones/new", NewMilestonePage.class, "r"); |
| | | mount("/milestones/edit", EditMilestonePage.class, "r", "h"); |
| | | mount("/mytickets", MyTicketsPage.class, "r", "h"); |
| | | |
| | | // setup the markup document urls |
| | | mount("/docs", DocsPage.class, "r"); |
| | |
| | | mount("/proposal", ReviewProposalPage.class, "t"); |
| | | mount("/registration", FederationRegistrationPage.class, "u", "n"); |
| | | |
| | | mount("/new", NewRepositoryPage.class); |
| | | mount("/edit", EditRepositoryPage.class, "r"); |
| | | mount("/activity", ActivityPage.class, "r", "h"); |
| | | mount("/lucene", LuceneSearchPage.class); |
| | | mount("/project", ProjectPage.class, "p"); |
| | |
| | | mount("/forks", ForksPage.class, "r"); |
| | | mount("/fork", ForkPage.class, "r"); |
| | | |
| | | // allow started Wicket plugins to initialize |
| | | for (PluginWrapper pluginWrapper : pluginManager.getPlugins()) { |
| | | if (PluginState.STARTED != pluginWrapper.getPluginState()) { |
| | | continue; |
| | | } |
| | | if (pluginWrapper.getPlugin() instanceof GitblitWicketPlugin) { |
| | | GitblitWicketPlugin wicketPlugin = (GitblitWicketPlugin) pluginWrapper.getPlugin(); |
| | | wicketPlugin.init(this); |
| | | } |
| | | } |
| | | |
| | | // customize the Wicket class resolver to load from plugins |
| | | IClassResolver coreResolver = getApplicationSettings().getClassResolver(); |
| | | PluginClassResolver classResolver = new PluginClassResolver(coreResolver, pluginManager); |
| | | getApplicationSettings().setClassResolver(classResolver); |
| | | |
| | | getMarkupSettings().setDefaultMarkupEncoding("UTF-8"); |
| | | super.init(); |
| | | } |
| | | |
| | | private void mount(String location, Class<? extends WebPage> clazz, String... parameters) { |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#mount(java.lang.String, java.lang.Class, java.lang.String) |
| | | */ |
| | | @Override |
| | | public void mount(String location, Class<? extends WebPage> clazz, String... parameters) { |
| | | if (parameters == null) { |
| | | parameters = new String[] {}; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#getHomePage() |
| | | */ |
| | | @Override |
| | | public Class<? extends WebPage> getHomePage() { |
| | | return homePageClass; |
| | | } |
| | | |
| | | public Class<? extends WebPage> getNewRepositoryPage() { |
| | | return newRepositoryPageClass; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#isCacheablePage(java.lang.String) |
| | | */ |
| | | @Override |
| | | public boolean isCacheablePage(String mountPoint) { |
| | | return cacheablePages.containsKey(mountPoint); |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#getCacheControl(java.lang.String) |
| | | */ |
| | | @Override |
| | | public CacheControl getCacheControl(String mountPoint) { |
| | | return cacheablePages.get(mountPoint); |
| | | } |
| | |
| | | return gitBlitWebSession; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#settings() |
| | | */ |
| | | @Override |
| | | public IStoredSettings settings() { |
| | | return settings; |
| | | } |
| | | |
| | | /** |
| | | * Is Gitblit running in debug mode? |
| | | * |
| | | * @return true if Gitblit is running in debug mode |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#isDebugMode() |
| | | */ |
| | | @Override |
| | | public boolean isDebugMode() { |
| | | return runtimeManager.isDebugMode(); |
| | | } |
| | |
| | | * These methods look strange... and they are... but they are the first |
| | | * step towards modularization across multiple commits. |
| | | */ |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#getBootDate() |
| | | */ |
| | | @Override |
| | | public Date getBootDate() { |
| | | return runtimeManager.getBootDate(); |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#getLastActivityDate() |
| | | */ |
| | | @Override |
| | | public Date getLastActivityDate() { |
| | | return repositoryManager.getLastActivityDate(); |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#runtime() |
| | | */ |
| | | @Override |
| | | public IRuntimeManager runtime() { |
| | | return runtimeManager; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#plugins() |
| | | */ |
| | | @Override |
| | | public IPluginManager plugins() { |
| | | return pluginManager; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#notifier() |
| | | */ |
| | | @Override |
| | | public INotificationManager notifier() { |
| | | return notificationManager; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#users() |
| | | */ |
| | | @Override |
| | | public IUserManager users() { |
| | | return userManager; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#authentication() |
| | | */ |
| | | @Override |
| | | public IAuthenticationManager authentication() { |
| | | return authenticationManager; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#keys() |
| | | */ |
| | | @Override |
| | | public IPublicKeyManager keys() { |
| | | return publicKeyManager; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#repositories() |
| | | */ |
| | | @Override |
| | | public IRepositoryManager repositories() { |
| | | return repositoryManager; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#projects() |
| | | */ |
| | | @Override |
| | | public IProjectManager projects() { |
| | | return projectManager; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#federation() |
| | | */ |
| | | @Override |
| | | public IFederationManager federation() { |
| | | return federationManager; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#gitblit() |
| | | */ |
| | | @Override |
| | | public IGitblit gitblit() { |
| | | return gitblit; |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#tickets() |
| | | */ |
| | | @Override |
| | | public ITicketService tickets() { |
| | | return gitblit.getTicketService(); |
| | | } |
| | | |
| | | /* (non-Javadoc) |
| | | * @see com.gitblit.wicket.Webapp#getTimezone() |
| | | */ |
| | | @Override |
| | | public TimeZone getTimezone() { |
| | | return runtimeManager.getTimezone(); |
| | | } |
| | |
| | | gb.status = status |
| | | gb.origin = origin |
| | | gb.headRef = default branch (HEAD) |
| | | gb.headRefDescription = change the ref that HEAD links to. e.g. refs/heads/master |
| | | gb.headRefDescription = The default branch that will be cloned and displayed on the Summary page. |
| | | gb.federationStrategy = federation strategy |
| | | gb.federationRegistration = federation registration |
| | | gb.federationResults = federation pull results |
| | |
| | | gb.noHits = no hits |
| | | gb.authored = authored |
| | | gb.committed = committed |
| | | gb.indexedBranches = indexed branches |
| | | gb.indexedBranchesDescription = select the branches to include in your Lucene index |
| | | gb.indexedBranches = Indexed Branches |
| | | gb.indexedBranchesDescription = Select the branches to be indexed by Lucene |
| | | gb.noIndexedRepositoriesWarning = none of your repositories are configured for Lucene indexing |
| | | gb.undefinedQueryWarning = query is undefined! |
| | | gb.noSelectedRepositoriesWarning = please select one or more repositories! |
| | |
| | | gb.ticketIsClosed = This ticket is closed. |
| | | gb.mergeToDescription = default integration branch for merging ticket patchsets |
| | | gb.anonymousCanNotPropose = Anonymous users can not propose patchsets. |
| | | gb.youDoNotHaveClonePermission = You are not permitted to clone this repository. |
| | | gb.youDoNotHaveClonePermission = You are not permitted to clone this repository. |
| | | gb.myTickets = my tickets |
| | | gb.yourAssignedTickets = assigned to you |
| | | gb.newMilestone = new milestone |
| | | gb.editMilestone = edit milestone |
| | | gb.deleteMilestone = Delete milestone \"{0}\"? |
| | | gb.milestoneDeleteFailed = Failed to delete milestone ''{0}''! |
| | | gb.notifyChangedOpenTickets = send notification for changed open tickets |
| | | gb.overdue = overdue |
| | | gb.openMilestones = open milestones |
| | | gb.closedMilestones = closed milestones |
| | | gb.administration = administration |
| | | gb.plugins = plugins |
| | | gb.extensions = extensions |
| | | gb.pleaseSelectProject = Please select the project! |
| | | gb.accessPolicy = Access Policy |
| | | gb.accessPolicyDescription = Choose an access policy to control repository visibility and git permissions. |
| | | gb.anonymousPolicy = Anonymous View, Clone, & Push |
| | | gb.anonymousPolicyDescription = Anyone can see, clone, and push to this repository. |
| | | gb.authenticatedPushPolicy = Restrict Push (Authenticated) |
| | | gb.authenticatedPushPolicyDescription = Anyone can see and clone this repository. All authenticated users have RW+ push permission. |
| | | gb.namedPushPolicy = Restrict Push (Named) |
| | | gb.namedPushPolicyDescription = Anyone can see and clone this repository. You choose who can push. |
| | | gb.clonePolicy = Restrict Clone & Push |
| | | gb.clonePolicyDescription = Anyone can see this repository. You choose who can clone and push. |
| | | gb.viewPolicy = Restrict View, Clone, & Push |
| | | gb.viewPolicyDescription = You choose who can see, clone, and push to this repository. |
| | | gb.initialCommit = Initial Commit |
| | | gb.initialCommitDescription = This will allow you to <code>git clone</code> this repository immediately. Skip this step if you have already run <code>git init</code> locally. |
| | | gb.initWithReadme = Include a README |
| | | gb.initWithReadmeDescription = This will generate a simple README document for your repository. |
| | | gb.initWithGitignore = Include a .gitignore file |
| | | gb.initWithGitignoreDescription = This will insert a config file that instructs your Git clients to ignore files or directories that match defined patterns. |
| | | gb.pleaseSelectGitIgnore = Please select a .gitignore file |
| | | gb.receive = receive |
| | | gb.permissions = permissions |
| | | gb.ownersDescription = Owners can manage all repository settings but they are not allowed to rename a repository unless it is their personal repository. |
| | | gb.userPermissionsDescription = You can specify individual user permissions. These settings will override team or regex permissions. |
| | | gb.teamPermissionsDescription = You can specify individual team permissions. These settings will override regex permissions. |
| | | gb.ticketSettings = Ticket Settings |
| | | gb.receiveSettings = Receive Settings |
| | | gb.receiveSettingsDescription = The receive settings control pushes to the repository. |
| | | gb.preReceiveDescription = Pre-receive hooks are executed after commits are received but <em>BEFORE</em> the refs are updated.<p>This is the appropriate hook for rejecting a push.</p> |
| | | gb.postReceiveDescription = Post-receive hooks are executed after commits are received but <em>AFTER</em> the refs are updated.<p>This is the appropriate hook for notifications, build triggers, etc.</p> |
| | | gb.federationStrategyDescription = Control if and how to federate this repository with another Gitblit. |
| | | gb.federationSetsDescription = This repository will be included in the selected federation sets. |
| | | gb.miscellaneous = miscellaneous |
| | | gb.originDescription = The url from which this repository was cloned. |
| | | gb.gc = GC |
| | | gb.garbageCollection = Garbage Collection |
| | | gb.garbageCollectionDescription = The garbage collector will pack loose objects pushed from clients and will remove unreferenced objects from the repository. |
| | | gb.commitMessageRendererDescription = Commit messages can be displayed as plaintext or as rendered markup. |
| | | gb.preferences = preferences |
| | | gb.accountPreferences = Account Preferences |
| | | gb.accountPreferencesDescription = Specify your account preferences |
| | | gb.languagePreference = Language Preference |
| | | gb.languagePreferenceDescription = Select your preferred translation for Gitblit |
| | | gb.emailMeOnMyTicketChanges = Email me on my ticket changes |
| | | gb.emailMeOnMyTicketChangesDescription = Send me an email notification for changes that I make to a ticket |
| | | gb.displayNameDescription = The preferred name for display |
| | | gb.emailAddressDescription = The primary email address for receiving notifications |
| | | gb.sshKeys = SSH Keys |
| | | gb.sshKeysDescription = SSH public key authentication is a secure alternative to password authentication |
| | | gb.addSshKey = Add SSH Key |
| | | gb.key = Key |
| | | gb.comment = 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 |
| | | gb.transportPreference = Transport Preference |
| | | gb.transportPreferenceDescription = Set the transport that you prefer to use for cloning |
New file |
| | |
| | | gb.repository = Repository |
| | | gb.owner = Besitzer |
| | | gb.description = Beschreibung |
| | | gb.lastChange = Letzte \u00c4nderung |
| | | gb.refs = Refs |
| | | gb.tag = Tag |
| | | gb.tags = Tags |
| | | gb.author = Autor |
| | | gb.committer = Committer |
| | | gb.commit = Commit |
| | | gb.age = Alter |
| | | gb.tree = Dateibaum |
| | | gb.parent = Parent |
| | | gb.url = URL |
| | | gb.history = Historie |
| | | gb.raw = Raw |
| | | gb.object = Object |
| | | gb.ticketId = Ticket Id |
| | | gb.ticketAssigned = Zugewiesen |
| | | gb.ticketOpenDate = Erstellt |
| | | gb.ticketStatus = Status |
| | | gb.ticketComments = Kommentare |
| | | gb.view = Ansicht |
| | | gb.local = Lokal |
| | | gb.remote = Remote |
| | | gb.branches = Branches |
| | | gb.patch = Patch |
| | | gb.diff = Diff |
| | | gb.log = Log |
| | | gb.moreLogs = Weitere Commits... |
| | | gb.allTags = Alle Tags... |
| | | gb.allBranches = Alle Branches... |
| | | gb.summary = \u00dcbersicht |
| | | gb.ticket = Ticket |
| | | gb.newRepository = Neues Repository |
| | | gb.newUser = Neuer Benutzer |
| | | gb.commitdiff = Commitdiff |
| | | gb.tickets = Tickets |
| | | gb.pageFirst = Anfang |
| | | gb.pagePrevious = Zur\u00fcck |
| | | gb.pageNext = Weiter |
| | | gb.head = HEAD |
| | | gb.blame = Blame |
| | | gb.login = Login |
| | | gb.logout = Logout |
| | | gb.username = Benutzername |
| | | gb.password = Passwort |
| | | gb.tagger = Tagger |
| | | gb.moreHistory = Mehr Historie... |
| | | gb.difftocurrent = Diff zu aktuellem Stand |
| | | gb.search = Suche |
| | | gb.searchForAuthor = Suche nach Commits von Autor |
| | | gb.searchForCommitter = Suche nach Commits von Committer |
| | | gb.addition = Neu |
| | | gb.modification = Modifikation |
| | | gb.deletion = L\u00f6schung |
| | | gb.rename = Umbenennung |
| | | gb.metrics = Metriken |
| | | gb.stats = Statistiken |
| | | gb.markdown = Markdown |
| | | gb.changedFiles = Ge\u00e4nderte Dateien |
| | | gb.filesAdded = {0} Dateien hinzugef\u00fcgt |
| | | gb.filesModified = {0} Dateien ge\u00e4ndert |
| | | gb.filesDeleted = {0} Dateien gel\u00f6scht |
| | | gb.filesCopied = {0} Dateien kopiert |
| | | gb.filesRenamed = {0} Dateien umbenannt |
| | | gb.missingUsername = Fehlender Benutzername |
| | | gb.edit = Bearbeiten |
| | | gb.searchTypeTooltip = Suchart ausw\u00e4hlen |
| | | gb.searchTooltip = Suche {0} |
| | | gb.delete = L\u00f6schen |
| | | gb.docs = Dokumentation |
| | | gb.accessRestriction = Zugriffsbeschr\u00e4nkung |
| | | gb.name = Name |
| | | gb.enableTickets = Tickets aktivieren |
| | | gb.enableDocs = Docs aktivieren |
| | | gb.save = Speichern |
| | | gb.showRemoteBranches = Zeige Remote Branches |
| | | gb.editUsers = Benutzer bearbeiten |
| | | gb.confirmPassword = Passwort best\u00e4tigen |
| | | gb.restrictedRepositories = Zugriffsbeschr\u00e4nkte Repositories |
| | | gb.canAdmin = Kann administrieren |
| | | gb.notRestricted = Anonymes Anzeigen, Klonen und Pushen |
| | | gb.pushRestricted = Authentifiziertes Pushen |
| | | gb.cloneRestricted = Authentifiziertes Klonen und Pushen |
| | | gb.viewRestricted = Authentifiziertes Anzeigen, Klonen und Pushen |
| | | gb.useTicketsDescription = Lesende Darstellung von Ticgit Issues |
| | | gb.useDocsDescription = Listet Markdown Dokumentation im Repository auf |
| | | gb.showRemoteBranchesDescription = Zeige Remote Branches |
| | | gb.canAdminDescription = Kann Gitblit Server administrieren |
| | | gb.permittedUsers = Zugelassene Benutzer |
| | | gb.isFrozen = ist eingefroren |
| | | gb.isFrozenDescription = Verbiete Push |
| | | gb.zip = Zip |
| | | gb.showReadme = Zeige Readme |
| | | gb.showReadmeDescription = Zeigt eine \"Readme\" Markdown Datei auf der Zusammenfassungsseite |
| | | gb.nameDescription = Verwenden Sie '/' um Repositories zu gruppieren. Z.B. libraries/mycoollib.git |
| | | gb.ownerDescription = Der Besitzer kann Repository-Einstellungen \u00e4ndern |
| | | gb.blob = Blob |
| | | gb.commitActivityTrend = Commit-Aktivit\u00e4tstrend |
| | | gb.commitActivityDOW = Commit-Aktivit\u00e4t nach Wochentag |
| | | gb.commitActivityAuthors = Prim\u00e4re Autoren nach Commit-Aktivit\u00e4t |
| | | gb.feed = Feed |
| | | gb.cancel = Abbrechen |
| | | gb.changePassword = Passwort \u00e4ndern |
| | | gb.isFederated = ist verbunden |
| | | gb.federateThis = Dieses Repository verbinden (Federation) |
| | | gb.federateOrigin = Ursprung (origin) verbinden (Federation) |
| | | gb.excludeFromFederation = Von Verbindung ausschlie\u00dfen (Federation) |
| | | gb.excludeFromFederationDescription = Verbiete verbundenen Gitblit Instanzen, von diesem Konto zu pullen (Federation) |
| | | gb.tokens = Federation Tokens |
| | | gb.tokenAllDescription = Alle Repositories, Benutzer und Einstellungen |
| | | gb.tokenUnrDescription = Alle Repositories und Benutzer |
| | | gb.tokenJurDescription = Alle Repositories |
| | | gb.federatedRepositoryDefinitions = Repositorydefinitionen |
| | | gb.federatedUserDefinitions = Benutzerdefinitionen |
| | | gb.federatedSettingDefinitions = Einstellungsdefinitionen |
| | | gb.proposals = Verbindungsanfrage (Federation) |
| | | gb.received = empfangen |
| | | gb.type = Typ |
| | | gb.token = Token |
| | | gb.repositories = Repositories |
| | | gb.proposal = Anfrage |
| | | gb.frequency = Frequenz |
| | | gb.folder = Ordner |
| | | gb.lastPull = Letzter Pull |
| | | gb.nextPull = N\u00e4chster Pull |
| | | gb.inclusions = Inclusions |
| | | gb.exclusions = Exclusions |
| | | gb.registration = Registrierungen |
| | | gb.registrations = Verbindungsregistrierungen |
| | | gb.sendProposal = Vorschlagen |
| | | gb.status = Status |
| | | gb.origin = Ursprung |
| | | gb.headRef = Default Branch (HEAD) |
| | | gb.headRefDescription = Der Default Branch, welcher gecloned und auf der Zusammenfassungsseite dargestellt wird |
| | | gb.federationStrategy = Verbindungsstrategie |
| | | gb.federationRegistration = Verbindungsregistrierung |
| | | gb.federationResults = Verbindungs-Pull-Ergebnis |
| | | gb.federationSets = federation sets |
| | | gb.message = Nachricht |
| | | gb.myUrlDescription = Die \u00f6ffentlich zugreifbare URL f\u00fcr Ihre Gitblit-Instanz |
| | | gb.destinationUrl = Senden an |
| | | gb.destinationUrlDescription = Die URL der Gitblit-Instanz, an welche die Anfrage gestellt werden soll |
| | | gb.users = Benutzer |
| | | gb.federation = Verbindungen (Federation) |
| | | gb.error = Fehler |
| | | gb.refresh = Aktualisieren |
| | | gb.browse = Durchsuchen |
| | | gb.clone = Clonen |
| | | gb.filter = Filter |
| | | gb.create = Erstellen |
| | | gb.servers = Server |
| | | gb.recent = K\u00fcrzlich |
| | | gb.available = Verf\u00fcgbar |
| | | gb.selected = Ausgew\u00e4hlt |
| | | gb.size = Gr\u00f6\u00dfe |
| | | gb.downloading = Wird heruntergeladen |
| | | gb.loading = Wird geladen |
| | | gb.starting = Wird gestartet |
| | | gb.general = Allgemein |
| | | gb.settings = Einstellungen |
| | | gb.manage = Verwalten |
| | | gb.lastLogin = Letzter Login |
| | | gb.skipSizeCalculation = \u00dcberspringe Gr\u00f6\u00dfenberechnung |
| | | gb.skipSizeCalculationDescription = Nicht die Gr\u00f6\u00dfe des Repositories berechnen (reduziert die Seitenladezeit) |
| | | gb.skipSummaryMetrics = \u00dcberspringe zusammenfassende Metriken |
| | | gb.skipSummaryMetricsDescription = Nicht die Metriken auf der Zusammenfassungsseite berechnen (reduziert die Seitenladezeit) |
| | | gb.accessLevel = Zugangsebene |
| | | gb.default = Default |
| | | gb.setDefault = Setze Default |
| | | gb.since = seit |
| | | gb.status = Status |
| | | gb.bootDate = Boot-Zeitpunkt |
| | | gb.servletContainer = Servlet container |
| | | gb.heapMaximum = Maximaler Heap |
| | | gb.heapAllocated = Allokierter Heap |
| | | gb.heapUsed = Verwendeter Heap |
| | | gb.free = Verf\u00fcgbar |
| | | gb.version = Version |
| | | gb.releaseDate = Releasedatum |
| | | gb.date = Datum |
| | | gb.activity = Aktivit\u00e4t |
| | | gb.subscribe = Subscribe |
| | | gb.branch = Branch |
| | | gb.maxHits = Max Hits |
| | | gb.recentActivity = K\u00fcrzliche Aktivit\u00e4t |
| | | gb.recentActivityStats = In den letzten {0} Tagen / {1} Commit(s) von {2} Autor(en) |
| | | gb.recentActivityNone = In den letzten {0} Tagen / Keine |
| | | gb.dailyActivity = T\u00e4gliche Aktivit\u00e4t |
| | | gb.activeRepositories = Aktive Repositories |
| | | gb.activeAuthors = Aktive Autoren |
| | | gb.commits = Commits |
| | | gb.teams = Teams |
| | | gb.teamName = Teamname |
| | | gb.teamMembers = Teammitglieder |
| | | gb.teamMemberships = Teammitgliedschaften |
| | | gb.newTeam = Neues Team |
| | | gb.permittedTeams = Zugelassene Teams |
| | | gb.emptyRepository = Leeres Repository |
| | | gb.repositoryUrl = Repository URL |
| | | gb.mailingLists = Mailinglisten |
| | | gb.preReceiveScripts = Pre-Receive Skripte |
| | | gb.postReceiveScripts = Post-Receive Skripte |
| | | gb.hookScripts = Hook Skripte |
| | | gb.customFields = Benutzerdefinierte Felder |
| | | gb.customFieldsDescription = Benutzerdefinierte Felder, die in Groovy Hooks zur Verf\u00fcgung stehen |
| | | gb.accessPermissions = Zugriffsberechtigungen |
| | | gb.filters = Filter |
| | | gb.generalDescription = Allgemeine Einstellungen |
| | | gb.accessPermissionsDescription = Zugriffseinschr\u00e4nkungen nach Benutzern und Teams |
| | | gb.accessPermissionsForUserDescription = Erstellen Sie Teammitgliedschaften oder gew\u00e4hren Sie Zugriff auf einzelnen Repositories |
| | | gb.accessPermissionsForTeamDescription = Weisen Sie Team Mitglieder zu oder gew\u00e4hren Sie Zugriff auf einzelne Repositories |
| | | gb.federationRepositoryDescription = Verbinden Sie dieses Repository mit anderen Gitblit Instanzen (Federation) |
| | | gb.hookScriptsDescription = Groovy Skripte beim Pushen auf diese Gitblit Instanz ausf\u00fchren |
| | | gb.reset = Reset |
| | | gb.pages = Seiten |
| | | gb.workingCopy = Arbeitskopie |
| | | gb.workingCopyWarning = Dieses Repository besitzt eine Arbeitskopie und kann keine Pushes empfangen |
| | | gb.query = Abfrage |
| | | gb.queryHelp = Standard Abfragesyntax wird unterst\u00fctzt.<p/><p/>Unter <a target="_new" href="http://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/queryparsersyntax.html">Lucene Query Parser Syntax</a> finden Sie weitere Details. |
| | | gb.queryResults = Ergebnisse {0} - {1} ({2} Treffer) |
| | | gb.noHits = Keine Treffer |
| | | gb.authored = ist Autor von |
| | | gb.committed = ist Comitter von |
| | | gb.indexedBranches = Indizierte Branches |
| | | gb.indexedBranchesDescription = W\u00e4hlen Sie die zu indizierenden Branches aus. |
| | | gb.noIndexedRepositoriesWarning = Keines Ihrer Repositories ist f\u00fcr die Indizierung durch Lucene konfiguriert. |
| | | gb.undefinedQueryWarning = Abfrage fehlt! |
| | | gb.noSelectedRepositoriesWarning = Bitte w\u00e4hlen Sie ein oder mehrere Repositories aus! |
| | | gb.luceneDisabled = Indizierung mit Lucene ist deaktiviert |
| | | gb.failedtoRead = Fehler beim Lesen |
| | | gb.isNotValidFile = ist keine g\u00fcltige Datei |
| | | gb.failedToReadMessage = Konnte Standard Nachricht von {0} nicht lesen! |
| | | gb.passwordsDoNotMatch = Passw\u00f6rter stimmen nicht \u00fcberein! |
| | | gb.passwordTooShort = Passwort ist zu kurz. Die minimale L\u00e4nge betr\u00e4gt {0} Zeichen. |
| | | gb.passwordChanged = Passwort erfolgreich ge\u00e4ndert. |
| | | gb.passwordChangeAborted = Passwort\u00e4nderung abgebrochen. |
| | | gb.pleaseSetRepositoryName = Bitte Repositorynamen angeben! |
| | | gb.illegalLeadingSlash = Pfade d\u00fcrfen nicht mit '/' beginnen. |
| | | gb.illegalRelativeSlash = Relative Pfade (../) sind nicht erlaubt. |
| | | gb.illegalCharacterRepositoryName = Repositoryname enth\u00e4lt nicht erlaubtes Zeichen ''{0}''! |
| | | gb.selectAccessRestriction = Bitte w\u00e4hlen Sie die Zugriffsbeschr\u00e4nkung aus! |
| | | gb.selectFederationStrategy = Bitte w\u00e4hlen Sie die Verbindungsstrategie (Federation) aus! |
| | | gb.pleaseSetTeamName = Bitte geben Sie einen Teamnamen an! |
| | | gb.teamNameUnavailable = Der Teamname ''{0}'' ist nicht verf\u00fcgbar. |
| | | gb.teamMustSpecifyRepository = Ein Team muss mindestens einem Repository zugewiesen sein. |
| | | gb.teamCreated = Neues Team ''{0}'' erfolgreich angelegt. |
| | | gb.pleaseSetUsername = Bitte geben Sie einen Benutzernamen an! |
| | | gb.usernameUnavailable = Benutzername ''{0}'' ist nicht verf\u00fcgbar. |
| | | gb.combinedMd5Rename = Gitblit ist f\u00fcr kombiniertes MD5-Passwort-Hashing konfiguriert. Sie m\u00fcssen beim Umbenennen des Kontos ein neues Passwort angeben. |
| | | gb.userCreated = Neuer Benutzer ''{0}'' erfolgreich angelegt. |
| | | gb.couldNotFindFederationRegistration = Konnte Verbindungsregistrierung (Federation) nicht finden! |
| | | gb.failedToFindGravatarProfile = Das Gravatar Profil f\u00fcr {0} konnte nicht gefunden werden |
| | | gb.branchStats = {0} Commit(s) und {1} Tag(s) seit {2} |
| | | gb.repositoryNotSpecified = Repository nicht angegeben! |
| | | gb.repositoryNotSpecifiedFor = Repository nicht angegeben f\u00fcr {0}! |
| | | gb.canNotLoadRepository = Repository kann nicht geladen werden |
| | | gb.commitIsNull = Commit ist null |
| | | gb.unauthorizedAccessForRepository = Nicht autorisierter Zugriff auf Repository |
| | | gb.failedToFindCommit = Commit \"{0}\" konnte nicht in {1} gefunden werden! |
| | | gb.couldNotFindFederationProposal = Verbindungsanfrage (Federation) konnte nicht gefunden werden! |
| | | gb.invalidUsernameOrPassword = Ung\u00fcltiger Benutzername oder Passwort! |
| | | gb.OneProposalToReview = Es gibt 1 unbeantwortete Verbindungsanfrage. |
| | | gb.nFederationProposalsToReview = Es gibt {0} unbeantwortete Verbindungsanfragen. |
| | | gb.couldNotFindTag = Der Tag {0} konnte nicht gefunden werden |
| | | gb.couldNotCreateFederationProposal = Die Verbindungsanfrage (Federation) konnte nicht erstellt werden. |
| | | gb.pleaseSetGitblitUrl = Bitte geben Sie Ihre Gitblit URL ein! |
| | | gb.pleaseSetDestinationUrl = Bitte geben Sie eine Ziel-URL f\u00fcr Ihre Anfrage ein! |
| | | gb.proposalReceived = Anfrage von {0} erfolgreich empfangen. |
| | | gb.noGitblitFound = Tut mir leid, {0} fand keine Gitblit Instanz in |
| | | gb.noProposals = Tut mir leid, {0} akzeptiert derzeit keine Anfragen. |
| | | gb.noFederation = Tut mir leid, {0} kann sich nicht mit anderen Gitblit Instanzen verbinden. |
| | | gb.proposalFailed = Tut mir leid, {0} hat keine Anfragedaten emfpangen! |
| | | gb.proposalError = Tut mir leid, {0} berichtet, dass ein unerwarteter Fehler aufgetreten ist! |
| | | gb.failedToSendProposal = Senden der Anfrage ist fehlgeschlagen! |
| | | gb.userServiceDoesNotPermitAddUser = {0} erlaubt das Anlegen von Benutzerkonten nicht. |
| | | gb.userServiceDoesNotPermitPasswordChanges = {0} erlaubt das \u00c4ndern von Passworten nicht! |
| | | gb.displayName = Anzeigename |
| | | gb.emailAddress = Emailadresse |
| | | gb.errorAdminLoginRequired = Administrierung erfordert eine Anmeldung |
| | | gb.errorOnlyAdminMayCreateRepository = Nur ein Administrator kann ein Repository erstellen |
| | | gb.errorOnlyAdminOrOwnerMayEditRepository = Nur ein Administrator oder der Besitzer kann ein Repository bearbeiten |
| | | gb.errorAdministrationDisabled = Administrierung ist deaktiviert |
| | | gb.lastNDays = letzte {0} Tage |
| | | gb.completeGravatarProfile = Komplettes Profil auf Gravatar.com |
| | | gb.none = keine |
| | | gb.line = Zeile |
| | | gb.content = Inhalt |
| | | gb.empty = leer |
| | | gb.inherited = vererbt |
| | | gb.deleteRepository = Repository \"{0}\" l\u00f6schen? |
| | | gb.repositoryDeleted = Repository ''{0}'' gel\u00f6scht. |
| | | gb.repositoryDeleteFailed = L\u00f6schen von Repository ''{0}'' fehlgeschlagen! |
| | | gb.deleteUser = Benutzer \"{0}\" l\u00f6schen? |
| | | gb.userDeleted = Benutzer ''{0}'' gel\u00f6scht. |
| | | gb.userDeleteFailed = L\u00f6schen von Benutzer ''{0}'' fehlgeschlagen! |
| | | gb.time.justNow = Gerade eben |
| | | gb.time.today = Heute |
| | | gb.time.yesterday = Gestern |
| | | gb.time.minsAgo = vor {0} Min. |
| | | gb.time.hoursAgo = vor {0} Std. |
| | | gb.time.daysAgo = vor {0} Tagen |
| | | gb.time.weeksAgo = vor {0} Wochen |
| | | gb.time.monthsAgo = vor {0} Monaten |
| | | gb.time.oneYearAgo = vor 1 Jahr |
| | | gb.time.yearsAgo = vor {0} Jahren |
| | | gb.duration.oneDay = 1 Tag |
| | | gb.duration.days = {0} Tage |
| | | gb.duration.oneMonth = 1 Monat |
| | | gb.duration.months = {0} Monaten |
| | | gb.duration.oneYear = 1 Jahr |
| | | gb.duration.years = {0} Jahren |
| | | gb.authorizationControl = Zugriffsrechte |
| | | gb.allowAuthenticatedDescription = Allen authentifizierten Benutzern RW+ Recht gew\u00e4hren |
| | | gb.allownameddescription = Benutzern und Teams feingranulare Rechte gew\u00e4hren |
| | | gb.markdownFailure = Markdown Inhalt konnte nicht geparst werden! |
| | | gb.clearCache = Cache leeren |
| | | gb.projects = Projekte |
| | | gb.project = Projekt |
| | | gb.allProjects = Alle Projekte |
| | | gb.copyToClipboard = in die Zwischenablage kopieren |
| | | gb.fork = Fork |
| | | gb.forks = Forks |
| | | gb.forkRepository = {0} forken? |
| | | gb.repositoryForked = Fork von {0} wurde erstellt |
| | | gb.repositoryForkFailed = Fork ist fehlgeschlagen |
| | | gb.personalRepositories = Pers\u00f6nliche Repositories |
| | | gb.allowForks = Forks erlauben |
| | | gb.allowForksDescription = Erlaube authentifizierten Benutzern dieses Repository zu forken |
| | | gb.forkedFrom = Fork von |
| | | gb.canFork = Kann forken |
| | | gb.canForkDescription = Kann autorisierte Repositories als pers\u00f6nliche Repositories forken |
| | | gb.myFork = Meinen Fork anschauen |
| | | gb.forksProhibited = Forks verboten |
| | | gb.forksProhibitedWarning = Dieses Repository verbietet Forks |
| | | gb.noForks = {0} hat keine Forks |
| | | gb.forkNotAuthorized = Entschuldigung, Sie sind nicht berechtigt einen Fork von {0} zu erstellen |
| | | gb.forkInProgress = Fork in Bearbeitung |
| | | gb.preparingFork = Ihr Fork wird vorbereitet... |
| | | gb.isFork = ist ein Fork |
| | | gb.canCreate = Kann Erstellen |
| | | gb.canCreateDescription = Kann pers\u00f6nliche Repositories erstellen |
| | | gb.illegalPersonalRepositoryLocation = your personal repository must be located at \"{0}\" |
| | | gb.verifyCommitter = Committer verifizieren |
| | | gb.verifyCommitterDescription = Die Committer Identit\u00e4t muss mit dem Gitblit Benutzerkonto \u00fcbereinstimmen, dass den Push durchf\u00fchrt |
| | | gb.verifyCommitterNote = Alle Merge Operationen ben\u00f6tigen "--no-ff" um die Committer Identit\u00e4t zu erzwingen |
| | | gb.repositoryPermissions = Repositoryberechtigungen |
| | | gb.userPermissions = Benutzerberechtigungen |
| | | gb.teamPermissions = Teamberechtigungen |
| | | gb.add = Hinzuf\u00fcgen |
| | | gb.noPermission = DIESE BERECHTIGUNG L\u00d6SCHEN |
| | | gb.excludePermission = {0} (Ausschlie\u00dfen) |
| | | gb.viewPermission = {0} (Ansicht) |
| | | gb.clonePermission = {0} (Clonen) |
| | | gb.pushPermission = {0} (Pushen) |
| | | gb.createPermission = {0} (Pushen, Erzeugen von Refs) |
| | | gb.deletePermission = {0} (Pushen, Erzeugen und L\u00f6schen von Refs) |
| | | gb.rewindPermission = {0} (Pushen, Erzeugen, L\u00f6schen und Umsetzen von Refs) |
| | | gb.permission = Berechtigung |
| | | gb.regexPermission = Diese Berechtigung ergibt sich aus dem regul\u00e4ren Ausdruck "{0}" |
| | | gb.accessDenied = Zugang verweigert |
| | | gb.busyCollectingGarbage = Tut mir leid, Gitblit f\u00fchrt gerade eine Garbage Collection in {0} durch |
| | | gb.gcPeriod = GC Intervall |
| | | gb.gcPeriodDescription = Zeitraum zwischen Garbage Collections |
| | | gb.gcThreshold = GC Schwellwert |
| | | gb.gcThresholdDescription = Minimale Gr\u00f6\u00dfe von losen Objekten, um eine vorzeitge Garbage Collection zu starten |
| | | gb.ownerPermission = Repositorybesitzer |
| | | gb.administrator = Administrator |
| | | gb.administratorPermission = Gitblit Administrator |
| | | gb.team = Team |
| | | gb.teamPermission = Berechtigung gesetzt durch Mitgliedschaft im Team \"{0}\" |
| | | gb.missing = fehlt! |
| | | gb.missingPermission = Das Repository f\u00fcr diese Berechtigung fehlt! |
| | | gb.mutable = ver\u00e4nderlich |
| | | gb.specified = angegeben |
| | | gb.effective = effektiv |
| | | gb.organizationalUnit = Organisatorische Einheit |
| | | gb.organization = Organisation |
| | | gb.locality = Lage |
| | | gb.stateProvince = Bundesland oder Provinz |
| | | gb.countryCode = L\u00e4ndercode |
| | | gb.properties = Eigenschaften |
| | | gb.issued = herausgegeben |
| | | gb.expires = l\u00e4uft ab |
| | | gb.expired = abgelaufen |
| | | gb.expiring = l\u00e4uft ab |
| | | gb.revoked = widerrufen |
| | | gb.serialNumber = Seriennummer |
| | | gb.certificates = Zertifkate |
| | | gb.newCertificate = Neues Zertifikat |
| | | gb.revokeCertificate = Zertifikat widerrufen |
| | | gb.sendEmail = Sende E-Mail |
| | | gb.passwordHint = Passwort Hinweis |
| | | gb.ok = OK |
| | | gb.invalidExpirationDate = Ung\u00fcltiges Ablaufdatum! |
| | | gb.passwordHintRequired = Passworthinweis ben\u00f6tigt! |
| | | gb.viewCertificate = Zertifikat anschauen |
| | | gb.subject = Betreff |
| | | gb.issuer = Aussteller |
| | | gb.validFrom = G\u00fcltig von |
| | | gb.validUntil = G\u00fcltig bis |
| | | gb.publicKey = \u00d6ffentlicher Schl\u00fcssel |
| | | gb.signatureAlgorithm = Signaturalgorithmus |
| | | gb.sha1FingerPrint = SHA-1 Fingerabdruck |
| | | gb.md5FingerPrint = MD5 Fingerabdruck |
| | | gb.reason = Grund |
| | | gb.revokeCertificateReason = Bitte w\u00e4hlen Sie einen Grund f\u00fcr den Widerruf des Zertifikats aus |
| | | gb.unspecified = nicht angegeben |
| | | gb.keyCompromise = Schl\u00fcssel kompromittiert |
| | | gb.caCompromise = CA kompromittiert |
| | | gb.affiliationChanged = Mitgliedschaft ge\u00e4ndert |
| | | gb.superseded = ersetzt |
| | | gb.cessationOfOperation = T\u00e4tigkeit eingestellt |
| | | gb.privilegeWithdrawn = Privilegien zur\u00fcckgezogen |
| | | gb.time.inMinutes = in {0} Minuten |
| | | gb.time.inHours = in {0} Stunden |
| | | gb.time.inDays = in {0} Tagen |
| | | gb.hostname = Hostname |
| | | gb.hostnameRequired = Bitte geben Sie einen Hostnamen ein |
| | | gb.newSSLCertificate = Neues Server-SSL-Zertifikat |
| | | gb.newCertificateDefaults = Voreinstellungen f\u00fcr neue Zertifikate |
| | | gb.duration = Dauer |
| | | gb.certificateRevoked = Zertifikat {0,number,0} wurde widerufen |
| | | gb.clientCertificateGenerated = Neues Client-Zertifikat f\u00fcr {0} wurde erfolgreich erstellt |
| | | gb.sslCertificateGenerated = Neues Server-SSL-Zertifikat f\u00fcr {0} wurde erfolgreich erstellt |
| | | gb.newClientCertificateMessage = ANMERKUNG:\nDas "Passwort" ist nicht das Passwort des Benutzers, es ist das Passwort, um den Keystore des Benutzers zu sch\u00fctzen. Dieses Passwort wird nicht gespeichert, also m\u00fcssen Sie einen "Hinweis" eingeben. Dieser Hinweis wird in den README Anweisungen des Benutzers hinterlegt. |
| | | gb.certificate = Zertifkat |
| | | gb.emailCertificateBundle = Client-Zertifikat-Bundle per Email senden |
| | | gb.pleaseGenerateClientCertificate = Bitte generieren Sie ein Client Zertifikat f\u00fcr {0} |
| | | gb.clientCertificateBundleSent = Client-Zertifikat-Bundel f\u00fcr {0} gesendet |
| | | gb.enterKeystorePassword = Bitte geben Sie das Gitblit-Keystore-Passwort ein |
| | | 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.maxActivityCommits = Maximale Commits Aktivit\u00e4t |
| | | gb.maxActivityCommitsDescription = Maximale Anzahl von Commits die auf der Aktivit\u00e4tsseite dargestellt werden |
| | | gb.noMaximum = Kein Maximum |
| | | gb.attributes = Attribute |
| | | gb.serveCertificate = Verwende dieses Zertifikat f\u00fcr HTTPS |
| | | gb.sslCertificateGeneratedRestart = Neues SSL-Server-Zertifikat f\u00fcr {0} erfolgreich erstellt.\nSie m\u00fcssen Gitblit neu starten, um dieses Zertifikat nutzen zu k\u00f6nnen.\n\nWenn Sie dem '--alias' Parameter starten, m\u00fcssen Sie diesen auf '--alias {0}' setzen. |
| | | gb.validity = G\u00fcltigkeit |
| | | gb.siteName = Seitenname |
| | | gb.siteNameDescription = Kurzer, beschreibender Name Ihres Servers |
| | | gb.excludeFromActivity = Von der Aktivi\u00e4tenseite ausschlie\u00dfen |
| | | gb.isSparkleshared = Repository ist in einem Sparkleshare |
| | | gb.owners = Besitzer |
| | | gb.sessionEnded = Die Sitzung wurde geschlossen |
| | | gb.closeBrowser = Bitte schlie\u00dfen Sie den Browser um die Sitzung ordentlich zu beenden. |
| | | gb.doesNotExistInTree = {0} existiert im Dateibaum {1} nicht |
| | | gb.enableIncrementalPushTags = Aktiviere inkrementelle Push-Tags |
| | | gb.useIncrementalPushTagsDescription = Erzeuge beim Push automatisch ein Tag mit aufsteigender Revisionsnummer auf der Spitze jedes Branches |
| | | gb.incrementalPushTagMessage = Auto-tagged [{0}] branch on push |
| | | gb.externalPermissions = {0} Zugangsberechtigungen werden extern verwaltet |
| | | gb.viewAccess = Sie haben keinen Gitblit Lese- oder Schreibzugriff |
| | | gb.overview = \u00dcbersicht |
| | | gb.dashboard = Dashboard |
| | | gb.monthlyActivity = Monatliche Aktivit\u00e4t |
| | | gb.myProfile = Mein Profil |
| | | gb.compare = Vergleichen |
| | | gb.manual = Manuell |
| | | gb.from = von |
| | | gb.to = nach |
| | | gb.at = bei |
| | | gb.of = von |
| | | gb.in = in |
| | | gb.moreChanges = alle \u00c4nderungen... |
| | | gb.pushedNCommitsTo = Push von {0} Commits nach |
| | | gb.pushedOneCommitTo = Push von einem Commit nach |
| | | gb.commitsTo = {0} commits nach |
| | | gb.oneCommitTo = 1 Commit nach |
| | | gb.byNAuthors = von {0} Autoren |
| | | gb.byOneAuthor = von {0} |
| | | gb.viewComparison = Zeige einen Vergleich von diesen {0} Commits \u00bb |
| | | gb.nMoreCommits = {0} weitere Commits \u00bb |
| | | gb.oneMoreCommit = 1 weiterer Commit \u00bb |
| | | gb.pushedNewTag = Push von neuem Tag |
| | | gb.createdNewTag = Neuer Tag angelegt |
| | | gb.deletedTag = Tag gel\u00f6scht |
| | | gb.pushedNewBranch = Push von neuem Branch durchgef\u00fchrt |
| | | gb.createdNewBranch = Neuer Branch angelegt |
| | | gb.deletedBranch = Branch gel\u00f6scht |
| | | gb.createdNewPullRequest = Neuer Pull Request gestellt |
| | | gb.mergedPullRequest = Merge des Pull Request durchgef\u00fchrt |
| | | gb.rewind = REWIND |
| | | gb.star = Favorisieren |
| | | gb.unstar = Nicht mehr favorisieren |
| | | gb.stargazers = Stargazers |
| | | gb.starredRepositories = Favorisierte Repositories |
| | | gb.failedToUpdateUser = Aktualisierung des Benutzerkontos fehlgeschlagen! |
| | | gb.myRepositories = Meine Repositories |
| | | gb.noActivity = In den letzten {0} Tagen gab es keine Aktivit\u00e4t |
| | | gb.findSomeRepositories = finde Repositories |
| | | gb.metricAuthorExclusions = Ausschl\u00fcsse von Autor-Metriken |
| | | gb.myDashboard = Mein Dashboard |
| | | gb.failedToFindAccount = Benutzerkonto "{0}" konnte nicht gefunden werden |
| | | gb.reflog = Reflog |
| | | gb.active = Aktiv |
| | | gb.starred = Favorisiert |
| | | gb.owned = Eigene |
| | | gb.starredAndOwned = Favorisiert und Eigene |
| | | gb.reviewPatchset = Review {0} Patchset {1} |
| | | gb.todaysActivityStats = Heute / {1} Commits von {2} Autoren |
| | | gb.todaysActivityNone = Heute / keine |
| | | gb.noActivityToday = Heute gab es keine Aktivit\u00e4t |
| | | gb.anonymousUser= Anonym |
| | | gb.commitMessageRenderer = Commit-Message Renderer |
| | | gb.diffStat = {0} Einf\u00fcgungen & {1} L\u00f6schungen |
| | | gb.home = Startseite |
| | | gb.isMirror = Dieses Repository ist ein Mirror |
| | | gb.mirrorOf = Mirror von {0} |
| | | gb.mirrorWarning = Dieses Repository ist ein Mirror und kann keine Pushes empfangen |
| | | gb.docsWelcome1 = Sie k\u00f6nnen Dokumente verwenden, um Ihr Repository zu dokumentieren. |
| | | gb.docsWelcome2 = Committen Sie eine README.md oder eine HOME.md Datei, um zu beginnen. |
| | | gb.createReadme = Eine README erstellen |
| | | gb.responsible = Bearbeiter |
| | | gb.createdThisTicket = erstellte dieses Ticket |
| | | gb.proposedThisChange = schlug diese \u00c4nderung vor |
| | | gb.uploadedPatchsetN = lud Patchset {0} hoch |
| | | gb.uploadedPatchsetNRevisionN = lud Patchset {0} Revision {1} hoch |
| | | gb.mergedPatchset = Merge des Patchset durchgef\u00fchrt |
| | | gb.commented = kommentierte |
| | | gb.noDescriptionGiven = keine Beschreibung hinterlegt |
| | | gb.toBranch = nach {0} |
| | | gb.createdBy = angelegt durch |
| | | gb.oneParticipant = {0} Teilnehmer |
| | | gb.nParticipants = {0} Teilnehmer |
| | | gb.noComments = keine Kommentare |
| | | gb.oneComment = {0} Kommentar |
| | | gb.nComments = {0} Kommentare |
| | | gb.oneAttachment = {0} Anhang |
| | | gb.nAttachments = {0} Anh\u00e4nge |
| | | gb.milestone = Meilenstein |
| | | gb.compareToMergeBase = Mit Merge-Basis vergleichen |
| | | gb.compareToN = mit {0} vergleichen |
| | | gb.open = Offen |
| | | gb.closed = Geschlossen |
| | | gb.merged = Merge erfolgt |
| | | gb.ticketPatchset = Ticket {0}, Patchset {1} |
| | | gb.patchsetMergeable = Dieses Patchset kann automatisch mit {0} zusammengef\u00fchrt werden. |
| | | gb.patchsetMergeableMore = Dieses Patchset kann auch auf der Kommandozeile mit {0} zusammengef\u00fchrt werden. |
| | | gb.patchsetAlreadyMerged = Dieses Patcheset wurde mit {0} zusammengef\u00fchrt. |
| | | gb.patchsetNotMergeable = Dieses Patchset kann nicht automatisch mit {0} zusammengef\u00fchrt werden. |
| | | gb.patchsetNotMergeableMore = Dieses Patchset ben\u00f6tigt einen Rebase oder muss manuell mit {0} zusammengef\u00fchrt werden, um Konflikte zu beheben. |
| | | gb.patchsetNotApproved = Diese Patchset-Revision wurde noch nicht zum Zusammenf\u00fchren mit {0} freigegeben. |
| | | gb.patchsetNotApprovedMore = Ein Reviewer muss dieses Patchset freigeben. |
| | | gb.patchsetVetoedMore = Ein Reviewer hat dieses Patchset abgelehnt. |
| | | gb.write = Verfassen |
| | | gb.comment = Kommentieren |
| | | gb.preview = Vorschau |
| | | gb.leaveComment = Hinterlasse einen Kommentar |
| | | gb.showHideDetails = Zeige/Verberge Details |
| | | gb.acceptNewPatchsets = Patchsets annehmen |
| | | gb.acceptNewPatchsetsDescription = Nimm Patchsets an dieses Repository per Push an |
| | | gb.acceptNewTickets = Erlaube neue Tickets |
| | | gb.acceptNewTicketsDescription = Erlaube das Erstellen von Fehlerberichten, Verbesserungsvorschl\u00e4gen, Aufgaben etc. |
| | | gb.requireApproval = Explizite Freigaben erforderlich |
| | | gb.requireApprovalDescription = Patchsets m\u00fcssen freigegeben werden, bevor der Merge Button aktiviert wird |
| | | gb.topic = Thema |
| | | gb.proposalTickets = Vorgeschlagene \u00c4nderungen |
| | | gb.bugTickets = Fehler |
| | | gb.enhancementTickets = Erweiterungen |
| | | gb.taskTickets = Aufgaben |
| | | gb.questionTickets = Fragen |
| | | gb.requestTickets = Erweiterungen und Aufgaben |
| | | gb.yourCreatedTickets = Von mir erstellt |
| | | gb.yourWatchedTickets = Von mir beobachtet |
| | | gb.mentionsMeTickets = Erw\u00e4hnungen |
| | | gb.updatedBy = aktualisiert von |
| | | gb.sort = Sortierung |
| | | gb.sortNewest = Neueste |
| | | gb.sortOldest = \u00c4lteste |
| | | gb.sortMostRecentlyUpdated = K\u00fcrzlich aktualisiert |
| | | gb.sortLeastRecentlyUpdated = Am l\u00e4ngsten nicht aktualisiert |
| | | gb.sortMostComments = Die meisten Kommentare |
| | | gb.sortLeastComments = Die wenigsten Kommentare |
| | | gb.sortMostPatchsetRevisions = Die meisten Patchset Revisions |
| | | gb.sortLeastPatchsetRevisions = Die wenigsten Patchset Revisions |
| | | gb.sortMostVotes = Die meisten Stimmen |
| | | gb.sortLeastVotes = Die wenigsten Stimmen |
| | | gb.topicsAndLabels = Themen & Labels |
| | | gb.milestones = Meilensteine |
| | | gb.noMilestoneSelected = Kein Meilenstein ausgew\u00e4hlt |
| | | gb.notSpecified = nicht angegebene |
| | | gb.due = f\u00e4llig am |
| | | gb.queries = Suchanfragen |
| | | gb.searchTicketsTooltip = Suche {0} Tickets |
| | | gb.searchTickets = Search Tickets |
| | | gb.new = Neu |
| | | gb.newTicket = Neues Ticket |
| | | gb.editTicket = Bearbeite Ticket |
| | | gb.ticketsWelcome = Sie k\u00f6nnen Tickets verwenden, um Ihre Todo-Liste zu verwalten, Fehler zu diskutieren und bei der Erstellung von Patchsets zusammen zu arbeiten. |
| | | gb.createFirstTicket = Erstellen Sie Ihr erstes Ticket |
| | | gb.title = \u00dcberschrift |
| | | gb.changedStatus = hat Status ge\u00e4ndert |
| | | gb.discussion = Diskussion |
| | | gb.updated = aktualisiert |
| | | gb.proposePatchset = Patchset Vorschlagen |
| | | gb.proposePatchsetNote = Bitte schlagen Sie ein Patchset f\u00fcr dieses Ticket vor. |
| | | gb.proposeInstructions = Um zu beginnen, erstellen Sie ein Patchset und laden Sie es mit Git hoch. Gitblit verkn\u00fcpft dieses Patchset mit diesem Ticket \u00fcber die Id. |
| | | gb.proposeWith = Ein Patchset mit {0} vorschlagen |
| | | gb.revisionHistory = Revisionshistorie |
| | | gb.merge = Zusammenf\u00fchren |
| | | gb.action = Aktion |
| | | gb.patchset = Patchset |
| | | gb.all = Alle |
| | | gb.mergeBase = Merge Basis |
| | | gb.checkout = Checkout |
| | | gb.checkoutViaCommandLine = Checkout per Kommandozeile |
| | | gb.checkoutViaCommandLineNote = Sie k\u00f6nnen diese \u00c4nderungen in Ihrem Clone des Repository per Checkout lokal testen. |
| | | gb.checkoutStep1 = Laden Sie das aktuelle Patchset \u2014 F\u00fchren Sie dies aus Ihrem lokalen Projektverzeichnis heraus aus |
| | | gb.checkoutStep2 = F\u00fchren Sie einen Checkout des Patchsets in einen neuen Branch durch und Sichten Sie die \u00c4nerungen |
| | | gb.mergingViaCommandLine = Merge per Kommandozeile |
| | | gb.mergingViaCommandLineNote = Wenn Sie den Merge Button nicht verwenden m\u00f6chten oder ein automatisches Zusammenf\u00fchren nicht durchgef\u00fchrt werden kann, dann k\u00f6nnen Sie das Zusammenf\u00fchren auch manuell auf der Kommandozeile durchf\u00fchren. |
| | | gb.mergeStep1 = Erstellen Sie einen neuen Branch um die \u00c4nderungen zu sichten \u2014 F\u00fchren Sie dies aus Ihrem lokalen Projektverzeichnis heraus aus |
| | | gb.mergeStep2 = Bringen Sie die vorgeschlagenen \u00c4nderungen ein und sichten Sie diese |
| | | gb.mergeStep3 = F\u00fchren Sie einen Merge durch und aktualisieren Sie den Server (Push) |
| | | gb.download = Herunterladen |
| | | gb.ptDescription = Das Gitblit Patchset Tool |
| | | gb.ptCheckout = Fetch & Checkout des aktuellen Patchset um ein Review des aktuellen Branch durchzuf\u00fchren |
| | | gb.ptMerge = Fetch & Merge des aktuellen Patchset in Ihren lokalen Branch |
| | | gb.ptDescription1 = Barnum ist ein Kommandozeilen-Werkzeug f\u00fcr Git um die Syntax f\u00fcr die Arbeit mit Gitblit Tickets und Patchsets zu vereinfachen. |
| | | gb.ptSimplifiedCollaboration = Vereinfachte Syntax f\u00fcr Zusammenarbeit |
| | | gb.ptSimplifiedMerge = Vereinfachte Syntax f\u00fcr das Zusammenf\u00fchren |
| | | gb.ptDescription2 = Barnum ben\u00f6tigt Python 3 und den nativen Git-Client. Es l\u00e4uft unter Windows, Linux und Mac OS X. |
| | | gb.stepN = Schritt {0} |
| | | gb.watchers = Beobachter |
| | | gb.votes = Stimmen |
| | | gb.vote = F\u00fcr {0} Abstimmen |
| | | gb.watch = {0} beobachten |
| | | gb.removeVote = Abstimmen r\u00fcckg\u00e4ngig machen |
| | | gb.stopWatching = Beobachten beenden |
| | | gb.watching = ich beobachte |
| | | gb.comments = Kommentare |
| | | gb.addComment = Kommentar hinzuf\u00fcgen |
| | | gb.export = Exportieren |
| | | gb.oneCommit = Ein Commit |
| | | gb.nCommits = {0} Commits |
| | | gb.addedOneCommit = 1 Commit hinzugef\u00fcgt |
| | | gb.addedNCommits = {0} Commits hinzugef\u00fcgt |
| | | gb.commitsInPatchsetN = Commits im Patchset {0} |
| | | gb.patchsetN = Patchset {0} |
| | | gb.reviewedPatchsetRev = Review von Patchset {0} Revision {1} durchgef\u00fchrt: {2} |
| | | gb.review = Review |
| | | gb.reviews = Reviews |
| | | gb.veto = Abgelehnt |
| | | gb.needsImprovement = Ben\u00f6tigt Verbesserungen |
| | | gb.looksGood = Sieht gut aus |
| | | gb.approve = Akzeptiert |
| | | gb.hasNotReviewed = kein Review durchgef\u00fchrt |
| | | gb.about = \u00dcber |
| | | gb.ticketN = Ticket #{0} |
| | | gb.disableUser = Benutzer deaktivieren |
| | | gb.disableUserDescription = Verhindert das Authentifizieren dieses Benutzer |
| | | gb.any = Alle |
| | | gb.milestoneProgress = {0} offen, {1} geschlossen |
| | | gb.nOpenTickets = {0} offen |
| | | gb.nClosedTickets = {0} geschlossen |
| | | gb.nTotalTickets = {0} insgesamt |
| | | gb.body = Body |
| | | gb.mergeSha = mergeSha |
| | | gb.mergeTo = Merge mit |
| | | gb.labels = Labels |
| | | gb.reviewers = Reviewer |
| | | gb.voters = Abstimmende |
| | | gb.mentions = Erw\u00e4hnungen |
| | | gb.canNotProposePatchset = Kann kein Patchset vorschlagen |
| | | gb.repositoryIsMirror = Dieses Repository ist ein Read-Only-Mirror. |
| | | gb.repositoryIsFrozen = Dieses Repository ist eingefroren. |
| | | gb.repositoryDoesNotAcceptPatchsets = Dieses Repository akzeptiert keine Patchsets. |
| | | gb.serverDoesNotAcceptPatchsets = Dieser Server akzeptiert keine Patchsets. |
| | | gb.ticketIsClosed = Dieses Ticket ist geschlossen. |
| | | gb.mergeToDescription = Standardm\u00e4\u00dfiger Integrationsbranch f\u00fcr den Merge von Ticket Patchsets |
| | | gb.anonymousCanNotPropose = Anonyme Benutzer k\u00f6nnen keine Patchsets vorschlagen. |
| | | gb.youDoNotHaveClonePermission = Sie sind nicht berechtigt, dieses Repository zu klonen. |
| | | gb.myTickets = Meine Tickets |
| | | gb.yourAssignedTickets = Mir zugewiesen |
| | | gb.newMilestone = Neuer Meilenstein |
| | | gb.editMilestone = Meilenstein bearbeiten |
| | | gb.deleteMilestone = Meilenstein \"{0}\" l\u00f6schen? |
| | | gb.milestoneDeleteFailed = L\u00f6schen des Meilensteins ''{0}'' fehlgeschlagen! |
| | | gb.notifyChangedOpenTickets = Sende Benachrichtigungen f\u00fcr ge\u00e4nderte, offene Tickets |
| | | gb.overdue = \u00dcberf\u00e4llig |
| | | gb.openMilestones = Offene Meilensteine |
| | | gb.closedMilestones = Geschlossene Meilensteine |
| | | gb.administration = Administration |
| | | gb.plugins = Plugins |
| | | gb.extensions = Erweiterungen |
| | | gb.pleaseSelectProject = Bitte w\u00e4hlen Sie das Projekt! |
| | | gb.accessPolicy = Zugriffsrichtlinie |
| | | gb.accessPolicyDescription = W\u00e4hlen Sie eine Zugriffsrichtlinie um die Sichtbarkeit des Repositories und die Zugriffsrechte von Git zu steuern. |
| | | gb.anonymousPolicy = Anonymes Anzeigen, Klonen und Pushen |
| | | gb.anonymousPolicyDescription = Jeder kann dieses Repository sehen, klonen und zu ihm pushen. |
| | | gb.authenticatedPushPolicy = Schr\u00e4nke Pushen ein (Authentifiziert) |
| | | gb.authenticatedPushPolicyDescription = Jeder kann dieses Repository sehen und klonen. Alle authentifizierten Benutzer haben RW+ Push Berechtigung. |
| | | gb.namedPushPolicy = Schr\u00e4nke Pushen ein (Benannt) |
| | | gb.namedPushPolicyDescription = Jeder kann dieses Repository sehen und klonen. Sie bestimmen, wer pushen kann. |
| | | gb.clonePolicy = Schr\u00e4nke Klonen und Pushen ein |
| | | gb.clonePolicyDescription = Jeder kann dieses Repository sehen. Sie bestimmen, wer klonen und pushen kann. |
| | | gb.viewPolicy = Schr\u00e4nke Anzeigen, Klonen und Pushen ein |
| | | gb.viewPolicyDescription = Sie bestimmen, wer dieses Repository anzeigen, klonen und zu ihm pushen kann. |
| | | gb.initialCommit = Initialer Commit |
| | | gb.initialCommitDescription = Dies erlaubt es Ihnen, mit <code>git clone</code> dieses Repository sofort zu klonen. \u00dcberspringen Sie diesen Schritt, falls Sie lokal bereits <code>git init</code> ausgef\u00fchrt haben. |
| | | gb.initWithReadme = README erstellen |
| | | gb.initWithReadmeDescription = Dies erstellt ein einfaches README Dokument f\u00fcr Ihr Repository. |
| | | gb.initWithGitignore = Eine .gitignore Datei erstellen |
| | | gb.initWithGitignoreDescription = Dies erstellt eine Konfigurationsdatei, die Ihren Git Client anweist, Dateien und Verzeichnisse zu ignorieren, die bestimmten Mustern entsprechen. |
| | | gb.pleaseSelectGitIgnore = Bitte w\u00e4hlen Sie eine .gitignore Datei aus |
| | | gb.receive = Empfangen |
| | | gb.permissions = Berechtigungen |
| | | gb.ownersDescription = Besitzer k\u00f6nnen alle Einstellungen des Repository ver\u00e4ndern, jedoch k\u00f6nnen Sie das Repository nur umbenennen, falls es ein pers\u00f6nliches Repository ist. |
| | | gb.userPermissionsDescription = Sie k\u00f6nnen individuelle Benutzerberechtigungen vergeben. Diese Einstellungen \u00fcbersteuern Team- oder Regexberechtigungen. |
| | | gb.teamPermissionsDescription = Sie k\u00f6nnen individuelle Teamberechtigungen vergeben. Diese Einstellungen \u00fcbersteuern Regexberechtigungen. |
| | | gb.ticketSettings = Ticketeinstellungen |
| | | gb.receiveSettings = Empfangseinstellungen |
| | | gb.receiveSettingsDescription = Die Empfangseinstellungen kontrollieren Pushes zum Repository. |
| | | gb.preReceiveDescription = Pre-Empfangs-Hooks werden ausgef\u00fchrt nachdem alle Commits empfangen wurden, aber <em>BEVOR</em> die Refs aktualisiert werden. <p>Dies ist der geeignete Hook, um einen Push abzulehnen.</p> |
| | | gb.postReceiveDescription = Post-Empfangs-Hooks werden ausgef\u00fchrt, nachdem alle Commits empfangen wurden und <em>NACHDEM</em> die Refs aktualisiert wurden. <p>Dies ist der geeignete Hook f\u00fcr Benachrichtigungen, Build-Trigger, etc.</p> |
| | | gb.federationStrategyDescription = Bestimmen Sie, ob und wie dieses Repository mit einer anderen Gitblit Instanz verbunden werden kann (Federation). |
| | | gb.federationSetsDescription = Dieses Repository wird in den ausgew\u00e4hlten Verbindungssets enthalten sein. |
| | | gb.miscellaneous = Sonstiges |
| | | gb.originDescription = Die URL, von welcher dieses Repository geklont wurde. |
| | | gb.gc = GC |
| | | gb.garbageCollection = Garbage Collection |
| | | gb.garbageCollectionDescription = Die Garbage Collection b\u00fcndelt freie Objekte, welche von Clients gepusht wurden und entfernt nicht mehr referenzierte Objekte aus dem Repository. |
| | | gb.commitMessageRendererDescription = Commit Messages k\u00f6nnen als reiner Text oder gerendertes Markup dargestellt werden. |
| | | gb.preferences = Einstellungen |
| | | gb.accountPreferences = Kontoeinstellungen |
| | | gb.accountPreferencesDescription = Geben Sie Ihre Kontoeinstellungen an |
| | | gb.languagePreference = Spracheinstellungen |
| | | gb.languagePreferenceDescription = W\u00e4hlen Sie Ihre bevorzugte \u00dcbersetzung f\u00fcr Gitblit |
| | | gb.emailMeOnMyTicketChanges = Sende Emails bei eigenen \u00c4nderungen an Tickets |
| | | gb.emailMeOnMyTicketChangesDescription = Sende mir Email-Benachrichtigungen f\u00fcr \u00c4nderungen, die ich an einem Ticket vornehme |
| | | gb.displayNameDescription = Bevorzugter Anzeigename |
| | | gb.emailAddressDescription = Die prim\u00e4re Emailadresse f\u00fcr den Empfang von Benachrichtigungen |
| | | gb.sshKeys = SSH Keys |
| | | gb.sshKeysDescription = SSH Public Key Authentifizierung ist eine sichere Alternative zur Authentifizierung mit Passwort |
| | | gb.addSshKey = SSH Key hinzuf\u00fcgen |
| | | gb.key = Key |
| | | gb.comment = Kommentar |
| | | gb.sshKeyCommentDescription = Geben Sie optional einen Kommentar ein. Falls Sie dies nicht tun, wird der Kommentar aus dem Key extrahiert. |
| | | gb.permission = Berechtigung |
| | | |
| | | gb.sshKeyPermissionDescription = Geben Sie die Zugriffberechtigung f\u00fcr den SSH Key an |
| | | gb.transportPreference = \u00dcbertragungseinstellungen |
| | | gb.transportPreferenceDescription = Geben Sie die \u00dcbertragungsart an, die Sie f\u00fcr das Klonen bevorzugen |
| | |
| | | gb.serverDoesNotAcceptPatchsets = Ce serveur n'accepte pas de patchsets. |
| | | gb.ticketIsClosed = Ce ticket est clos. |
| | | gb.mergeToDescription = default integration branch for merging ticket patchsets |
| | | gb.myTickets = mes tickets |
| | | gb.yourAssignedTickets = dont vous êtes responsable |
New file |
| | |
| | | gb.repository = repository |
| | | gb.owner = proprietario |
| | | gb.description = descrizione |
| | | gb.lastChange = ultima modifica |
| | | gb.refs = refs |
| | | gb.tag = tag |
| | | gb.tags = tags |
| | | gb.author = autore |
| | | gb.committer = committer |
| | | gb.commit = commit |
| | | gb.age = età |
| | | gb.tree = albero |
| | | gb.parent = padre |
| | | gb.url = URL |
| | | gb.history = cronologia |
| | | gb.raw = originale |
| | | gb.object = oggetto |
| | | gb.ticketId = id del ticket |
| | | gb.ticketAssigned = assegnato |
| | | gb.ticketOpenDate = data di apertura |
| | | gb.ticketStatus = stato |
| | | gb.ticketComments = commenti |
| | | gb.view = vista |
| | | gb.local = locale |
| | | gb.remote = remoto |
| | | gb.branches = rami |
| | | gb.patch = patch |
| | | gb.diff = differenze |
| | | gb.log = log |
| | | gb.moreLogs = ulteriori commits... |
| | | gb.allTags = tutte le tags... |
| | | gb.allBranches = tutti i rami... |
| | | gb.summary = riassunto |
| | | gb.ticket = ticket |
| | | gb.newRepository = nuovo repository |
| | | gb.newUser = nuovo utente |
| | | gb.commitdiff = differenze di commit |
| | | gb.tickets = elenco ticket |
| | | gb.pageFirst = prima |
| | | gb.pagePrevious = prec |
| | | gb.pageNext = succ |
| | | gb.head = HEAD |
| | | gb.blame = annotazioni |
| | | gb.login = login |
| | | gb.logout = logout |
| | | gb.username = nome utente |
| | | gb.password = password |
| | | gb.tagger = autore della tag |
| | | gb.moreHistory = ulteriore cronoligia... |
| | | gb.difftocurrent = differenze con il corrente |
| | | gb.search = ricerca |
| | | gb.searchForAuthor = Ricerca commit per autore |
| | | gb.searchForCommitter = Ricerca commit per committer |
| | | gb.addition = aggiunta |
| | | gb.modification = modifica |
| | | gb.deletion = cancellazione |
| | | gb.rename = rinomina |
| | | gb.metrics = metriche |
| | | gb.stats = statistiche |
| | | gb.markdown = markdown |
| | | gb.changedFiles = file modificati |
| | | gb.filesAdded = {0} file aggiunti |
| | | gb.filesModified = {0} file modificati |
| | | gb.filesDeleted = {0} file cancellati |
| | | gb.filesCopied = {0} file copiati |
| | | gb.filesRenamed = {0} file rinominati |
| | | gb.missingUsername = Nome Utente Mancante |
| | | gb.edit = modifica |
| | | gb.searchTypeTooltip = Seleziona tipo di ricerca |
| | | gb.searchTooltip = Ricerca {0} |
| | | gb.delete = cancella |
| | | gb.docs = documentazione |
| | | gb.accessRestriction = restrizioni di accesso |
| | | gb.name = nome |
| | | gb.enableTickets = abilita supporto ticket |
| | | gb.enableDocs = abilita documentazione |
| | | gb.save = salva |
| | | gb.showRemoteBranches = mostra i rami remoti |
| | | gb.editUsers = modifica utenti |
| | | gb.confirmPassword = conferma password |
| | | gb.restrictedRepositories = repository con restrizioni di accesso |
| | | gb.canAdmin = controllo completo |
| | | gb.notRestricted = visualizzazione, clone e push anonimi |
| | | gb.pushRestricted = push previa autenticazione |
| | | gb.cloneRestricted = clone e push previa autenticazione |
| | | gb.viewRestricted = visualizzazione, clone e push previa autenticazione |
| | | gb.useTicketsDescription = segnalazioni Ticgit distribuite (sola lettura) |
| | | gb.useDocsDescription = elenca la documentazione Markdown nel repository |
| | | gb.showRemoteBranchesDescription = mostra rami remoti |
| | | gb.canAdminDescription = può amministrare il server Gitblit |
| | | gb.permittedUsers = utenti autorizzati |
| | | gb.isFrozen = sola lettura |
| | | gb.isFrozenDescription = operazioni di push vietate |
| | | gb.zip = zip |
| | | gb.showReadme = mostra readme |
| | | gb.showReadmeDescription = mostra un file \"readme\" in formato Markdown nella pagina riassuntiva |
| | | gb.nameDescription = utilizza '/' per raggruppare i repository. p.e. libraries/mycoollib.git |
| | | gb.ownerDescription = il proprietario può modificare le impostazioni del repository |
| | | gb.blob = blob |
| | | gb.commitActivityTrend = tendenza dell'attività di commit |
| | | gb.commitActivityDOW = commit per giorno della settimana |
| | | gb.commitActivityAuthors = autori principali sulla base dei commit |
| | | gb.feed = feed |
| | | gb.cancel = annulla |
| | | gb.changePassword = cambia password |
| | | gb.isFederated = federato |
| | | gb.federateThis = attiva federazione su questo repository |
| | | gb.federateOrigin = attiva federazione su origin |
| | | gb.excludeFromFederation = escludi dalla federazione |
| | | gb.excludeFromFederationDescription = impedisci a istanze federate di Gitblit di effettuare il pull su questo utente |
| | | gb.tokens = gettoni di federazione |
| | | gb.tokenAllDescription = tutti i repository, utenti e impostazioni |
| | | gb.tokenUnrDescription = tutti i repository e gli utenti |
| | | gb.tokenJurDescription = tutti i repository |
| | | gb.federatedRepositoryDefinitions = definizione dei repository |
| | | gb.federatedUserDefinitions = definizione degli utenti |
| | | gb.federatedSettingDefinitions = definizione delle impostazioni |
| | | gb.proposals = proposta di federazione |
| | | gb.received = ricevuta |
| | | gb.type = tipo |
| | | gb.token = gettone |
| | | gb.repositories = repository |
| | | gb.proposal = proposta |
| | | gb.frequency = frequenza |
| | | gb.folder = cartella |
| | | gb.lastPull = ultimo pull |
| | | gb.nextPull = prossimo pull |
| | | gb.inclusions = inclusioni |
| | | gb.exclusions = esclusioni |
| | | gb.registration = registrazione |
| | | gb.registrations = registrationi di federazione |
| | | gb.sendProposal = proponi |
| | | gb.status = stato |
| | | gb.origin = origin |
| | | gb.headRef = ramo predefinito (HEAD) |
| | | gb.headRefDescription = Il ramo predefinito soggetto a clone e visualizzato nella pagina riassuntiva |
| | | gb.federationStrategy = strategia di federazione |
| | | gb.federationRegistration = registrazione di federazione |
| | | gb.federationResults = risultati di pull federato |
| | | gb.federationSets = insiemi di federazione |
| | | gb.message = messaggio |
| | | gb.myUrlDescription = URL pubblico alla tua istanza Gitblit |
| | | gb.destinationUrl = invia a |
| | | gb.destinationUrlDescription = URL dell'istanza Gitblit a cui inviare la proposta |
| | | gb.users = utenti |
| | | gb.federation = federazione |
| | | gb.error = errore |
| | | gb.refresh = aggiorna |
| | | gb.browse = sfoglia |
| | | gb.clone = clona |
| | | gb.filter = filtra |
| | | gb.create = crea |
| | | gb.servers = server |
| | | gb.recent = recenti |
| | | gb.available = disponibile |
| | | gb.selected = selezionato |
| | | gb.size = dimensione |
| | | gb.downloading = download in corso |
| | | gb.loading = caricamento |
| | | gb.starting = avvio |
| | | gb.general = generale |
| | | gb.settings = impostazioni |
| | | gb.manage = gestisci |
| | | gb.lastLogin = ultimo login |
| | | gb.skipSizeCalculation = non computare le dimensioni |
| | | gb.skipSizeCalculationDescription = disabilita la computazione delle dimensioni del repository (velocizza caricamento pagine) |
| | | gb.skipSummaryMetrics = ometti il riassunto delle metriche |
| | | gb.skipSummaryMetricsDescription = non calcolare le metriche nella pagina riassuntiva (velocizza caricamento pagine) |
| | | gb.accessLevel = livello di access |
| | | gb.default = predefinito |
| | | gb.setDefault = imposta predefinito |
| | | gb.since = da |
| | | gb.status = stato |
| | | gb.bootDate = data di avvio del server |
| | | gb.servletContainer = servlet container |
| | | gb.heapMaximum = memoria massima |
| | | gb.heapAllocated = memoria allocata |
| | | gb.heapUsed = memoria utilizzata |
| | | gb.free = libero |
| | | gb.version = versione |
| | | gb.releaseDate = data di rilascio |
| | | gb.date = data |
| | | gb.activity = attività |
| | | gb.subscribe = sottoscrivi |
| | | gb.branch = ramo |
| | | gb.maxHits = max hits |
| | | gb.recentActivity = attività recenti |
| | | gb.recentActivityStats = ultimi {0} giorni / {1} commit da {2} autori |
| | | gb.recentActivityNone = ultimi {0} giorni / nessuno |
| | | gb.dailyActivity = attività giornaliera |
| | | gb.activeRepositories = repository attivi |
| | | gb.activeAuthors = autori attivi |
| | | gb.commits = commit |
| | | gb.teams = gruppi |
| | | gb.teamName = nome del gruppo |
| | | gb.teamMembers = membry del gruppo |
| | | gb.teamMemberships = appartenenza al gruppo |
| | | gb.newTeam = nuovo gruppo |
| | | gb.permittedTeams = gruppi autorizzati |
| | | gb.emptyRepository = repository vuoto |
| | | gb.repositoryUrl = repository URL |
| | | gb.mailingLists = liste di corrispondenza |
| | | gb.preReceiveScripts = script eseguiti su pre-receive |
| | | gb.postReceiveScripts = script eseguiti su post-receive |
| | | gb.hookScripts = script eseguiti su hook di git |
| | | gb.customFields = campi peronalizzati |
| | | gb.customFieldsDescription = campi personalizzati accessibili a hook scritti in Groovy |
| | | gb.accessPermissions = permessi di accesso |
| | | gb.filters = filtri |
| | | gb.generalDescription = impostazioni comuni |
| | | gb.accessPermissionsDescription = riduci l'accesso in base a utenti e gruppi |
| | | gb.accessPermissionsForUserDescription = imposta appartenenza a un gruppo o abilita accesso a repository soggetti a restrizioni |
| | | gb.accessPermissionsForTeamDescription = imposta i membri di un gruppo e abilita accesso a repository soggetti a restrizioni |
| | | gb.federationRepositoryDescription = condividi questo repository con altre istanze Gitblit |
| | | gb.hookScriptsDescription = esegue script Groovy quando viene effettuato un push su questo server |
| | | gb.reset = reimposta |
| | | gb.pages = pagine |
| | | gb.workingCopy = copia di lavoro |
| | | gb.workingCopyWarning = questo repository è una copia di lavoro a non ammette push |
| | | gb.query = interrogazione |
| | | gb.queryHelp = La sintassi standard è supportata.<p/><p/>Si vedi <a target="_new" href="http://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/queryparsersyntax.html">Lucene Query Parser Syntax</a> per ulteriori dettagli. |
| | | gb.queryResults = risultati {0} - {1} ({2} corrispondenze) |
| | | gb.noHits = nessuna corrispondenza |
| | | gb.authored = creato da |
| | | gb.committed = commit di |
| | | gb.indexedBranches = Rami Indicizzati |
| | | gb.indexedBranchesDescription = Seleziona i rami che devono essere indicizzati tramite Lucene |
| | | gb.noIndexedRepositoriesWarning = nessun repository è soggetto a indicizzazione Lucene |
| | | gb.undefinedQueryWarning = interrogazione non specificata! |
| | | gb.noSelectedRepositoriesWarning = per favore specifica uno o più repository! |
| | | gb.luceneDisabled = Indicizzazione tramite Lucene disabilitata |
| | | gb.failedtoRead = Errore di lettura |
| | | gb.isNotValidFile = non è un file valido |
| | | gb.failedToReadMessage = Errore nella lettura del messaggio da {0}! |
| | | gb.passwordsDoNotMatch = La password non corissponde! |
| | | gb.passwordTooShort = La password è troppo corta. La lunghezza minima è {0} caratteri. |
| | | gb.passwordChanged = Password modificata con successo. |
| | | gb.passwordChangeAborted = Modifica della password annullata. |
| | | gb.pleaseSetRepositoryName = Specificare il nome del repository! |
| | | gb.illegalLeadingSlash = Riferiementi alla cartella principale (/) non sono ammessi. |
| | | gb.illegalRelativeSlash = Riferimenti relativi a cartelle (../) non sono ammessi. |
| | | gb.illegalCharacterRepositoryName = Carattere non consetito ''{0}'' nel nome del repository! |
| | | gb.selectAccessRestriction = Restrizioni di accesso non specificate! |
| | | gb.selectFederationStrategy = Strategia di federazione non selezionata! |
| | | gb.pleaseSetTeamName = Nome del gruppo non specificato! |
| | | gb.teamNameUnavailable = Il nome di gruppo ''{0}'' non è disponibile. |
| | | gb.teamMustSpecifyRepository = Un gruppo deve specificare almeno un repository. |
| | | gb.teamCreated = Nuovo gruppo ''{0}'' creato con successo. |
| | | gb.pleaseSetUsername = Nome utente non specificato! |
| | | gb.usernameUnavailable = Il nome utente ''{0}'' non è disponibile. |
| | | gb.combinedMd5Rename = Gitblit è configurato per effettuare un hashing delle password di tipo combinato-md5. E' quindi necessario specificare una nuova password quando si rinomina un utenza. |
| | | gb.userCreated = Nuovo utente ''{0}'' creato con successo. |
| | | gb.couldNotFindFederationRegistration = Impossibile trovare la registrazione di federazione! |
| | | gb.failedToFindGravatarProfile = Profilo Gravatar per {0} non reperito! |
| | | gb.branchStats = {2} contiene {0} commit e {1} tag |
| | | gb.repositoryNotSpecified = Repository non specificato! |
| | | gb.repositoryNotSpecifiedFor = Repository non specificato per {0}! |
| | | gb.canNotLoadRepository = Impossibile leggere il repository |
| | | gb.commitIsNull = Commit nullo |
| | | gb.unauthorizedAccessForRepository = Accesso al repository non autorizzato |
| | | gb.failedToFindCommit = Cmmit \"{0}\" non trovato in {1}! |
| | | gb.couldNotFindFederationProposal = Impossibile trovare la proposta di federazione! |
| | | gb.invalidUsernameOrPassword = Nome utente o password non validi! |
| | | gb.OneProposalToReview = 1 proposta di federazione è in attesa di valutazione. |
| | | gb.nFederationProposalsToReview = Ci sono {0} proposte di federazione in attesa di valutazione |
| | | gb.couldNotFindTag = Tag non trovata {0} |
| | | gb.couldNotCreateFederationProposal = Impossibile creare proposta di federazione! |
| | | gb.pleaseSetGitblitUrl = Gitblit URL non specificato! |
| | | gb.pleaseSetDestinationUrl = URL di destinazione non specificato! |
| | | gb.proposalReceived = Proposta ricevuta da {0} con successo. |
| | | gb.noGitblitFound = {0} non ha potuto trovare una istanza di Gitblit presso {1}. |
| | | gb.noProposals = {0} al momento non accetta proposte. |
| | | gb.noFederation = {0} non è configurato per creare una federazione con altre istanze Gitblit. |
| | | gb.proposalFailed = {0} non ha ricevuto alcuna proposta di federazione! |
| | | gb.proposalError = {0} segnala un errore inatteso! |
| | | gb.failedToSendProposal = Invio proposta fallito! |
| | | gb.userServiceDoesNotPermitAddUser = {0} non consete di aggiungere nuovi utenti! |
| | | gb.userServiceDoesNotPermitPasswordChanges = {0} non consente di cambiare la password! |
| | | gb.displayName = nome pubblico |
| | | gb.emailAddress = indirizzo email |
| | | gb.errorAdminLoginRequired = Effettuare l'accesso per utilizzare le funzioni amministrative |
| | | gb.errorOnlyAdminMayCreateRepository = Solo un utente amministratore può creare repository |
| | | gb.errorOnlyAdminOrOwnerMayEditRepository = Solo un utente amministratore e il proprietario possono modificare un repository |
| | | gb.errorAdministrationDisabled = Funzioni amministrative disabilitate |
| | | gb.lastNDays = Ultimi {0} giorni |
| | | gb.completeGravatarProfile = Completa il profilo su Gravatar.com |
| | | gb.none = nessuno |
| | | gb.line = linea |
| | | gb.content = contenuto |
| | | gb.empty = vuoto |
| | | gb.inherited = ereditato |
| | | gb.deleteRepository = Cancellare il repository \"{0}\"? |
| | | gb.repositoryDeleted = Repository ''{0}'' cancellato. |
| | | gb.repositoryDeleteFailed = Impossible cancellare il repository ''{0}''! |
| | | gb.deleteUser = Cancellare l'utente \"{0}\"? |
| | | gb.userDeleted = Utente ''{0}'' cancellato. |
| | | gb.userDeleteFailed = Impossibile cancellare l'utente ''{0}''! |
| | | gb.time.justNow = in questo istante |
| | | gb.time.today = oggi |
| | | gb.time.yesterday = ieri |
| | | gb.time.minsAgo = {0} minuti fa |
| | | gb.time.hoursAgo = {0} ore fa |
| | | gb.time.daysAgo = {0} giorni fa |
| | | gb.time.weeksAgo = {0} settimane fa |
| | | gb.time.monthsAgo = {0} mese fa |
| | | gb.time.oneYearAgo = 1 anno fa |
| | | gb.time.yearsAgo = {0} anni fa |
| | | gb.duration.oneDay = 1 giorno |
| | | gb.duration.days = {0} giorni |
| | | gb.duration.oneMonth = 1 mese |
| | | gb.duration.months = {0} mesi |
| | | gb.duration.oneYear = 1 anno |
| | | gb.duration.years = {0} anni |
| | | gb.authorizationControl = Controlli di autorizzazine |
| | | gb.allowAuthenticatedDescription = Consenti lettura/scrittura a tutti gli utenti registrati |
| | | gb.allowNamedDescription = Configura permessi specifici per utenti e gruppi |
| | | gb.markdownFailure = Impossibile leggere contenuto Markdown! |
| | | gb.clearCache = pulisci la cache |
| | | gb.projects = progetti |
| | | gb.project = progetto |
| | | gb.allProjects = tutti i progetti |
| | | gb.copyToClipboard = copia negli appunti |
| | | gb.fork = ramificazione |
| | | gb.forks = ramificazioni |
| | | gb.forkRepository = crea una ramificazione {0}? |
| | | gb.repositoryForked = ramificazione creata per {0} |
| | | gb.repositoryForkFailed= ramificazione fallita |
| | | gb.personalRepositories = repository personali |
| | | gb.allowForks = consenti ramificazioni |
| | | gb.allowForksDescription = consenti agli utenti autorizzati di creare ramificazioni di questo repository |
| | | gb.forkedFrom = ramificazione di |
| | | gb.canFork = creare ramificazioni |
| | | gb.canForkDescription = può creare una ramificazione personale a partire da un repository cui ha accesso |
| | | gb.myFork = vedere le mie ramificazioni |
| | | gb.forksProhibited = ramificazioni vietate |
| | | gb.forksProhibitedWarning = questo repository non ammette ramificazioni |
| | | gb.noForks = {0} non ha ramificazioni |
| | | gb.forkNotAuthorized = non sei autorizzato a crare una ramificazione di {0} |
| | | gb.forkInProgress = ramificazione in corso |
| | | gb.preparingFork = ramificazione in preparazione... |
| | | gb.isFork = è una ramificazione |
| | | gb.canCreate = può creare |
| | | gb.canCreateDescription = può creare repository personali |
| | | gb.illegalPersonalRepositoryLocation = i tuoi repository personali devono trovarsi \"{0}\" |
| | | gb.verifyCommitter = verifica committer |
| | | gb.verifyCommitterDescription = controlla che l'identità del committer corrisponda all'utente Gitblit di push |
| | | gb.verifyCommitterNote = tutti i merge richiedono "--no-ff" per verificare l'identità del committer |
| | | gb.repositoryPermissions = permessi di repository |
| | | gb.userPermissions = permessi di utente |
| | | gb.teamPermissions = permessi di gruppo |
| | | gb.add = aggiungi |
| | | gb.noPermission = CANCELLA QUESTO PERMESSO |
| | | gb.excludePermission = {0} (esclude) |
| | | gb.viewPermission = {0} (visualizza) |
| | | gb.clonePermission = {0} (clone) |
| | | gb.pushPermission = {0} (push) |
| | | gb.createPermission = {0} (push, crea refs) |
| | | gb.deletePermission = {0} (push, crea e cancella refs) |
| | | gb.rewindPermission = {0} (push, crea cancella e riavvolge ref) |
| | | gb.permission = permesso |
| | | gb.regexPermission = questo permesso è assegnato tramite espressione regolare \"{0}\" |
| | | gb.accessDenied = accesso negato |
| | | gb.busyCollectingGarbage = Gitblit sta eseguendo manutenzione su {0} |
| | | gb.gcPeriod = Intervallo di GC |
| | | gb.gcPeriodDescription = Intervallo di tempo tra un GC e il successivo |
| | | gb.gcThreshold = soglia di GC |
| | | gb.gcThresholdDescription = soglia minima di oggetti eliminabili che innesca un GC (garbage collection) anticipato |
| | | gb.ownerPermission = proprietario del repository |
| | | gb.administrator = amministratore |
| | | gb.administratorPermission = amministratore di Gitblit |
| | | gb.team = gruppo |
| | | gb.teamPermission = permesso ottenuto attraverso l'appartenenza al gruppo \"{0}\" |
| | | gb.missing = mancante! |
| | | gb.missingPermission = il repository per questo permesso è mancante! |
| | | gb.mutable = mutabile |
| | | gb.specified = specificato |
| | | gb.effective = effettivo |
| | | gb.organizationalUnit = unità organizzativa |
| | | gb.organization = organizzazione |
| | | gb.locality = località |
| | | gb.stateProvince = stato o provincia |
| | | gb.countryCode = codice nazione |
| | | gb.properties = proprietà |
| | | gb.issued = segnalato |
| | | gb.expires = scade |
| | | gb.expired = scaduto |
| | | gb.expiring = in scadenza |
| | | gb.revoked = revocato |
| | | gb.serialNumber = numero di serie |
| | | gb.certificates = certificati |
| | | gb.newCertificate = nuovo certificato |
| | | gb.revokeCertificate = revoca certificato |
| | | gb.sendEmail = spedisci email |
| | | gb.passwordHint = domanda di sicurezza |
| | | gb.ok = ok |
| | | gb.invalidExpirationDate = data di scadenza invalida! |
| | | gb.passwordHintRequired = la domanda di sicurezza è obbligatoria! |
| | | gb.viewCertificate = vedi certificato |
| | | gb.subject = soggetto |
| | | gb.issuer = emesso da |
| | | gb.validFrom = valid dal |
| | | gb.validUntil = valido fino al |
| | | gb.publicKey = chiave pubblica |
| | | gb.signatureAlgorithm = algoritml di firma |
| | | gb.sha1FingerPrint = firma SHA-1 |
| | | gb.md5FingerPrint = firma MD5 |
| | | gb.reason = motivazione |
| | | gb.revokeCertificateReason = Per favore selezionare una motivazione per la revoca del certificato |
| | | gb.unspecified = non specificata |
| | | gb.keyCompromise = chiave compromessa |
| | | gb.caCompromise = CA compromessa |
| | | gb.affiliationChanged = cambio di affiliazione |
| | | gb.superseded = obsoleto |
| | | gb.cessationOfOperation = cessata attività |
| | | gb.privilegeWithdrawn = privilegio rimosso |
| | | gb.time.inMinutes = in {0} minuti |
| | | gb.time.inHours = in {0} ore |
| | | gb.time.inDays = in {0} giorni |
| | | gb.hostname = nome host |
| | | gb.hostnameRequired = Per favore specificare un nome host |
| | | gb.newSSLCertificate = nuovo certificato SSL per il server |
| | | gb.newCertificateDefaults = nuovi valori predefiniti del certificato |
| | | gb.duration = durata |
| | | gb.certificateRevoked = Il certificato {0,number,0} è stato revocato |
| | | gb.clientCertificateGenerated = Nuovo certificato client generato con successo per {0} |
| | | gb.sslCertificateGenerated = Nuovo certificato SSL server generato con successo per {0} |
| | | gb.newClientCertificateMessage = NOTA:\nLa 'password' non è la password dell'utente, bensì la password per il portachiavi (keystore). Questa password non è salvata, perciò è necessario specificare una domanda di sicurezza che sarà inclusa nelle istruzioni per l'utente (README) |
| | | gb.certificate = certificato |
| | | gb.emailCertificateBundle = invia in email il pacchetto del certificato |
| | | gb.pleaseGenerateClientCertificate = Per favore generare un certificato client per {0} |
| | | gb.clientCertificateBundleSent = Il pacchetto contente il certificato client per {0} è stato spedito |
| | | gb.enterKeystorePassword = Per favore digita la password per il portachiavi di Gitblit (keystore) |
| | | gb.warning = attenzione |
| | | gb.jceWarning = Il runtime Java in use non contiene i files \"JCE Unlimited Strength Jurisdiction Policy\".\nQuesto limita la lunghezza della password del portachiavi a 7 caratteri.\nI file mancanti possono essere scaricati dal sito Oracle.\n\nVuoi continuare e generare il certificato comunque?\n\nSe rispondi No il tuo browser verrà redirezionato alla pagina di download di Oracle. |
| | | gb.maxActivityCommits = numero di commit nella pagina attività |
| | | gb.maxActivityCommitsDescription = numero massimo di commit da visualizzare nella pagina attività |
| | | gb.noMaximum = nessun limite |
| | | gb.attributes = attributi |
| | | gb.serveCertificate = utilizza questo certificato per HTTPS |
| | | gb.sslCertificateGeneratedRestart = Certificato SSL server generato con successo per {0}.\nE' necessario riavviare Gitblit per utilizzare il nuovo certificato.\n\nSe l'applicazione à avviata con il parametro '--alias', sarà necesario impostare tale parametro a ''--alias {0}''. |
| | | gb.validity = validità |
| | | gb.siteName = nome del sito |
| | | gb.siteNameDescription = nome breve del server |
| | | gb.excludeFromActivity = escludi dalla pagina riassuntiva delle attività |
| | | gb.isSparkleshared = il repository si trova una cartella Sparkleshare |
| | | gb.owners = proprietari |
| | | gb.sessionEnded = La sessione è terminata |
| | | gb.closeBrowser = Chiudere il browser per terminare correttamente la sessione. |
| | | gb.doesNotExistInTree = {0} non esiste nell'albero {1} |
| | | gb.enableIncrementalPushTags = abilita push incrementale di tag |
| | | gb.useIncrementalPushTagsDescription = A seguito di un push, crea automaticamente una etichetta in cima ad ogni ramificazione utilizzando un numero incrementale |
| | | gb.incrementalPushTagMessage = Nuova auto-etichetta su ramificazione [{0}] a seguito di push |
| | | gb.externalPermissions = {0} i permessi di accesso sono gestiti su un sistema esterno |
| | | gb.viewAccess = Non hai accesso in lettura o scrittura su Gitblit |
| | | gb.overview = riassunto |
| | | gb.dashboard = cruscotto |
| | | gb.monthlyActivity = attività mensile |
| | | gb.myProfile = il mio profilo |
| | | gb.compare = confronta |
| | | gb.manual = manuale |
| | | gb.from = da |
| | | gb.to = a |
| | | gb.at = al |
| | | gb.of = di |
| | | gb.in = in |
| | | gb.moreChanges = tutti i cambiamenti... |
| | | gb.pushedNCommitsTo = ha effettuato il push di {0} nuovi commit |
| | | gb.pushedOneCommitTo = ha effettuato il push di 1 nuovo commit |
| | | gb.commitsTo = {0} crea commits su |
| | | gb.oneCommitTo = 1 commit su |
| | | gb.byNAuthors = da {0} authori |
| | | gb.byOneAuthor = da {0} |
| | | gb.viewComparison = confronta qeusti {0} commit \u00bb |
| | | gb.nMoreCommits = {0} altri commit \u00bb |
| | | gb.oneMoreCommit = 1 altro commit \u00bb |
| | | gb.pushedNewTag = ha effettuato il push di una nuova tag |
| | | gb.createdNewTag = ha creato una nuova tag |
| | | gb.deletedTag = ha cancellato una tag |
| | | gb.pushedNewBranch = ha effettuato il push di una ramificazione |
| | | gb.createdNewBranch = ha creato una nuova ramificazione |
| | | gb.deletedBranch = ha cancellato una ramificazione |
| | | gb.createdNewPullRequest = ha creato una richiesta di pull |
| | | gb.mergedPullRequest = ha eseguito il merge di una richiesta di pull |
| | | gb.rewind = RIAVVOLGERE |
| | | gb.star = aggiungi stella |
| | | gb.unstar = togli stella |
| | | gb.stargazers = astronomi |
| | | gb.starredRepositories = repository stellati |
| | | gb.failedToUpdateUser = Aggiornamento utente fallito! |
| | | gb.myRepositories = I miei repository |
| | | gb.noActivity = nessuna attività negli ultimi {0} giorni |
| | | gb.findSomeRepositories = trova repository |
| | | gb.metricAuthorExclusions = Esclusione autori dalle metriche |
| | | gb.myDashboard = il mio cruscotto |
| | | gb.failedToFindAccount = utente non trovato ''{0}'' |
| | | gb.reflog = reflog |
| | | gb.active = attivo |
| | | gb.starred = stellato |
| | | gb.owned = posseduto |
| | | gb.starredAndOwned = stellato e posseduto |
| | | gb.reviewPatchset = revisione di {0} insiemi di patch {1} |
| | | gb.todaysActivityStats = oggi / {1} commit da {2} autori |
| | | gb.todaysActivityNone = oggi / nessuno |
| | | gb.noActivityToday = nessuna attività oggi |
| | | gb.anonymousUser= anonimo |
| | | gb.commitMessageRenderer = visualizzatore messaggio di commit |
| | | gb.diffStat = {0} aggiunte & {1} cancellazioni |
| | | gb.home = home |
| | | gb.isMirror = questo repository è uno specchio |
| | | gb.mirrorOf = specchio di {0} |
| | | gb.mirrorWarning = questo repository è uno specchio e non ammette push |
| | | gb.docsWelcome1 = Puoi usare file per documentare il tuo repository |
| | | gb.docsWelcome2 = Crea un file README.md o HOME.md per cominciare. |
| | | gb.createReadme = crea un README |
| | | gb.responsible = responsabile |
| | | gb.createdThisTicket = ha creato questo ticket |
| | | gb.proposedThisChange = ha proposto questo cambiamento |
| | | gb.uploadedPatchsetN = ha fatto l'upload di una patch {0} |
| | | gb.uploadedPatchsetNRevisionN = ha aggiornato la patch {0} alla revisione {1} |
| | | gb.mergedPatchset = ha effettuato il merge di una patch |
| | | gb.commented = ha commentato |
| | | gb.noDescriptionGiven = nessuna descrizione |
| | | gb.toBranch = a {0} |
| | | gb.createdBy = creato da |
| | | gb.oneParticipant = {0} partecipante |
| | | gb.nParticipants = {0} partecipanti |
| | | gb.noComments = nessun comment |
| | | gb.oneComment = {0} commento |
| | | gb.nComments = {0} commenti |
| | | gb.oneAttachment = {0} allegato |
| | | gb.nAttachments = {0} allegati |
| | | gb.milestone = milestone |
| | | gb.compareToMergeBase = confronta con la base di merge |
| | | gb.compareToN = confronta con {0} |
| | | gb.open = aperto |
| | | gb.closed = chiuso |
| | | gb.merged = merge effettuato |
| | | gb.ticketPatchset = ticket {0}, patch {1} |
| | | gb.patchsetMergeable = Questa patch può essere sottoposta a merge automatico con {0}. |
| | | gb.patchsetMergeableMore = Questa patch può anche sottoposta a merge con {0} dalla riga di comando. |
| | | gb.patchsetAlreadyMerged = Questa patch è stata sottoposta a merge con {0}. |
| | | gb.patchsetNotMergeable = Non è possibile effettuare il merge automatico di questa patch con {0}. |
| | | gb.patchsetNotMergeableMore = Questa patch necessita di rebase o merge manuale con {0} per risolvere i conflitti. |
| | | gb.patchsetNotApproved = La revisione di questa patch non à stata approvata per il merge con {0}. |
| | | gb.patchsetNotApprovedMore = Questa patch richiede approvazione da parte di un revisore. |
| | | gb.patchsetVetoedMore = Un revisore ha rifiutato questa patch. |
| | | gb.write = scrittura |
| | | gb.comment = commento |
| | | gb.preview = anteprima |
| | | gb.leaveComment = lascia un commento... |
| | | gb.showHideDetails = mostra/nascondi dettagli |
| | | gb.acceptNewPatchsets = accetta patch |
| | | gb.acceptNewPatchsetsDescription = accetta patch per questo repository |
| | | gb.acceptNewTickets = consenti nuovi ticket |
| | | gb.acceptNewTicketsDescription = consente la creazione di ticket per difetti, migliorie, attività, etc |
| | | gb.requireApproval = approvazione richiesta |
| | | gb.requireApprovalDescription = le patch devono essere approvate affinchè il bottone merge venga abilitato |
| | | gb.topic = argomento |
| | | gb.proposalTickets = cambiamenti proposti |
| | | gb.bugTickets = difetti |
| | | gb.enhancementTickets = migliorie |
| | | gb.taskTickets = attività |
| | | gb.questionTickets = domande |
| | | gb.requestTickets = migliorie e attività |
| | | gb.yourCreatedTickets = create da te |
| | | gb.yourWatchedTickets = osservate da te |
| | | gb.mentionsMeTickets = in cui sei menzionato |
| | | gb.updatedBy = aggiornate da |
| | | gb.sort = ordina |
| | | gb.sortNewest = più nuovi |
| | | gb.sortOldest = più vecchi |
| | | gb.sortMostRecentlyUpdated = aggiornati più di recente |
| | | gb.sortLeastRecentlyUpdated = aggiornati meno di recente |
| | | gb.sortMostComments = più commenti |
| | | gb.sortLeastComments = meno commenti |
| | | gb.sortMostPatchsetRevisions = patch con più revisioni |
| | | gb.sortLeastPatchsetRevisions = patch con meno revisioni |
| | | gb.sortMostVotes = più votati |
| | | gb.sortLeastVotes = meno votati |
| | | gb.topicsAndLabels = argomenti ed etichette |
| | | gb.milestones = milestone |
| | | gb.noMilestoneSelected = nessuna milestone selezionata |
| | | gb.notSpecified = non specificato |
| | | gb.due = entro |
| | | gb.queries = interrogazioni |
| | | gb.searchTicketsTooltip = ricerca {0} ticket |
| | | gb.searchTickets = ricerca ticket |
| | | gb.new = nuovo |
| | | gb.newTicket = nuovo ticket |
| | | gb.editTicket = modifica ticket |
| | | gb.ticketsWelcome = Puoi usare i ticket per creare una lista di cose da fare, discutere i difetti o collaborare su patch. |
| | | gb.createFirstTicket = Crea il tuo primo ticket |
| | | gb.title = Titolo |
| | | gb.changedStatus = ha cambibato lo stato |
| | | gb.discussion = discussione |
| | | gb.updated = aggiornato |
| | | gb.proposePatchset = proponi una patch |
| | | 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.proposeWith = Proponi una patch con {0} |
| | | gb.revisionHistory = cronologia revisioni |
| | | gb.merge = merge |
| | | gb.action = azione |
| | | gb.patchset = patch |
| | | gb.all = all |
| | | gb.mergeBase = base di merge |
| | | gb.checkout = checkout |
| | | gb.checkoutViaCommandLine = Checkout da riga di comando |
| | | gb.checkoutViaCommandLineNote = Puoi effettuare il checkout e testare questi cambiamenti localmente tramite il tuo clone di questo repository. |
| | | gb.checkoutStep1 = Esegui il fetch della patch corrente \u2014 esegui questo dalla tua cartella di progetto |
| | | gb.checkoutStep2 = Esegui il checkout della patch in una nuova ramificazione e revisione |
| | | gb.mergingViaCommandLine = Esecuzione del merge via command line |
| | | gb.mergingViaCommandLineNote = Se non vuoi utilizzare il bottone di merge, oppure il merge automatico non è possibile, puoi eseguire il merge manuale da riga di comando. |
| | | gb.mergeStep1 = Esegui il checkout di un nuovo branch per esaminare i cambiamenti \u2014 esegui questo dalla tua cartella di progetto |
| | | gb.mergeStep2 = Apporta i cambiamenti proposti ed esegui la revisione |
| | | gb.mergeStep3 = Effettua il merge dei cambiamenti proposti e poi aggiorna il server |
| | | gb.download = download |
| | | gb.ptDescription = strumento di Gitblit per le patch |
| | | gb.ptCheckout = Esegui il fetch e il checkout della patch corrente in una nuova ramificazione per la revisione |
| | | gb.ptMerge = Esegui il fetch e il checkout della patch corrente in una tua ramificazione locale |
| | | gb.ptDescription1 = Barnum è un accessorio a riga di comando per Git che semplifica la sintassi per lavorare con i ticket Gitblit e le patch |
| | | gb.ptSimplifiedCollaboration = sintassi semplificata di collaborazione |
| | | gb.ptSimplifiedMerge = sintassi semplificata di merge |
| | | gb.ptDescription2 = Barnum richiede Python 3 e il client Git nativo. Funziona su Windows, Linux, and Mac OS X. |
| | | gb.stepN = Passo {0} |
| | | gb.watchers = osservatori |
| | | gb.votes = voti |
| | | gb.vote = vota per questo {0} |
| | | gb.watch = osserva questo {0} |
| | | gb.removeVote = annulla voto |
| | | gb.stopWatching = non osservare più |
| | | gb.watching = osservati |
| | | gb.comments = commenti |
| | | gb.addComment = aggiungi un commento |
| | | gb.export = esporta |
| | | gb.oneCommit = un commit |
| | | gb.nCommits = {0} commit |
| | | gb.addedOneCommit = aggiunto 1 commit |
| | | gb.addedNCommits = aggiunti {0} commit |
| | | gb.commitsInPatchsetN = commit nella pactch {0} |
| | | gb.patchsetN = patch {0} |
| | | gb.reviewedPatchsetRev = patch analizzata {0} revisione {1}: {2} |
| | | gb.review = revisione |
| | | gb.reviews = revisioni |
| | | gb.veto = veto |
| | | gb.needsImprovement = da migliorare |
| | | gb.looksGood = sembra buona |
| | | gb.approve = approvata |
| | | gb.hasNotReviewed = non analizzata |
| | | gb.about = a proposito di |
| | | gb.ticketN = ticket #{0} |
| | | gb.disableUser = disabilita utente |
| | | gb.disableUserDescription = blocca l'utente impedendone l'autenticazione |
| | | gb.any = qualsiasi |
| | | gb.milestoneProgress = {0} aperti, {1} chiusi |
| | | gb.nOpenTickets = {0} aperti |
| | | gb.nClosedTickets = {0} chiusi |
| | | gb.nTotalTickets = {0} totali |
| | | gb.body = corpo |
| | | gb.mergeSha = SHA del merge |
| | | gb.mergeTo = merge con |
| | | gb.labels = etichette |
| | | gb.reviewers = revisori |
| | | gb.voters = votanti |
| | | gb.mentions = menzioni |
| | | gb.canNotProposePatchset = patch non accettate |
| | | gb.repositoryIsMirror = Questo repository è uno specchio di sola lettura. |
| | | gb.repositoryIsFrozen = Questo repository è congelato. |
| | | gb.repositoryDoesNotAcceptPatchsets = Questo repository non ammette patch. |
| | | gb.serverDoesNotAcceptPatchsets = Questo server non ammette patch. |
| | | gb.ticketIsClosed = Questo ticket è chiuso. |
| | | gb.mergeToDescription = ramificazione di integrazione per il merge di patch per ticket |
| | | gb.anonymousCanNotPropose = Utenti anonimi non possono proporre patch. |
| | | gb.youDoNotHaveClonePermission = Non hai i diritti per effettuare il clone di questo repository. |
| | | gb.myTickets = i miei ticket |
| | | gb.yourAssignedTickets = assegnati a te |
| | | gb.newMilestone = nuova milestone |
| | | gb.editMilestone = modifica milestone |
| | | gb.deleteMilestone = Cancella milestone \"{0}\"? |
| | | gb.milestoneDeleteFailed = Cancellazione di milestone fallita ''{0}''! |
| | | gb.notifyChangedOpenTickets = invia notifiche per cambiamenti su ticket aperti |
| | | gb.overdue = oltre il termine |
| | | gb.openMilestones = milestone aperte |
| | | gb.closedMilestones = milestone chiuse |
| | | gb.administration = amministrazione |
| | | gb.plugins = plugins |
| | | gb.extensions = estensioni |
| | | gb.pleaseSelectProject = Per favore seleziona il progetto! |
| | | gb.accessPolicy = Politica di accesso |
| | | gb.accessPolicyDescription = Scegli una politica di accesso per controllare la visibilità del repository e i permessi git. |
| | | gb.anonymousPolicy = Visualizzazione, Clone & Push anonimi |
| | | gb.anonymousPolicyDescription = Chiunque può visualizzare, clonare ed fare push su questo repository. |
| | | gb.authenticatedPushPolicy = Push ristretto (utenti autenticati) |
| | | gb.authenticatedPushPolicyDescription = Chiunque può visualizzare e clonare questo repository. Tutti gli utenti autenticati hanno diritto a push. |
| | | gb.namedPushPolicy = Push ristretto (utenti specifici) |
| | | gb.namedPushPolicyDescription = Chiunque può visualizzare e clonare questo repository. Solo gli utenti selezioni hanno diritto al push. |
| | | gb.clonePolicy = Clone & Push ristretti |
| | | gb.clonePolicyDescription = Chiunque può visualizzare questo repository. I permessi di clone e push vanno definiti. |
| | | gb.viewPolicy = Visualizzazione, Clone, & Push ristretti |
| | | gb.viewPolicyDescription = Vanno definiti i permessi per stabilire chi può visualizzare, clonare ed effettuare il push su questo repository. |
| | | gb.initialCommit = Primo commit |
| | | gb.initialCommitDescription = Questa funzionalità ti consente di clonare questo repository immediatamente. Salta questo passo se hai già un repository locale inizializzato. |
| | | gb.initWithReadme = Includi un README |
| | | gb.initWithReadmeDescription = Questa funzionalità genera semplice README per il tuo repository |
| | | gb.initWithGitignore = Includi un file .gitignore |
| | | gb.initWithGitignoreDescription = Questa funzionalità aggiunge un file di configurazione che istruisce i client Git ad ignorare file o cartelle che corrispondono a determinati criteri di selezione. |
| | | gb.pleaseSelectGitIgnore = Scegli un file .gitignore |
| | | gb.receive = ricevi |
| | | gb.permissions = permessi |
| | | gb.ownersDescription = Tutti i proprietari possono gestire tutti le impostazioni del repository ma non è concessa la rinomina del repository tranne nel caso di repository personale. |
| | | gb.userPermissionsDescription = E' possibile configurare permessi individuali. Queste impostazioni sovrascrivono quelle ereditate dal gruppo o da associazione tramite espresisone regolare. |
| | | gb.teamPermissionsDescription = E' possibile specificare permessi di gruppo. Queste impostazioni sovrascrivono quelle ereditate da associazione tramite espressione regolare. |
| | | gb.ticketSettings = Impostazioni Ticket |
| | | gb.receiveSettings = Ricezione ticket |
| | | gb.receiveSettingsDescription = Le impostazioni di ricezione governano i push al repository |
| | | gb.preReceiveDescription = Gli hook di pre-receive sono eseguiti dopo aver ricevuto i commit ma <em>PRIMA</em> che i ref vengano aggiornati.<p>Questo è l'hook da usare per rigettare un push</p> |
| | | gb.postReceiveDescription = Gli hook di post-receive sono eseguiti dopo aver ricevuto i commit e <em>DOPO</em> che i ref sono stati aggiornati.<p>Questo è l'hook da usare per inviare notifiche, attivare un sistema di build ecc.</p> |
| | | gb.federationStrategyDescription = Stabilisce se e come federare questo repository con un altra istanza Gitblit. |
| | | gb.federationSetsDescription = Questo repository sarà incluso nelle federazioni selezionate. |
| | | gb.miscellaneous = miscellanea |
| | | gb.originDescription = URL da cui questo repository è stato clonato |
| | | gb.gc = GC |
| | | gb.garbageCollection = Garbage Collection |
| | | gb.garbageCollectionDescription = Lo spazzino (GC) comprimerà gli oggetti inviati da client Git and rimuoverà dal repository oggetti non più referenziati. |
| | | gb.commitMessageRendererDescription = I messaggi di commit possono essere visualizzati come testo semplice o decorati come markdown |
| | | gb.preferences = impostazioni |
| | | gb.accountPreferences = Impostazione Utente |
| | | gb.accountPreferencesDescription = Imposta le preferenze del tuo utente |
| | | gb.languagePreference = Impostazioni di lingua |
| | | gb.languagePreferenceDescription = Scegli la tua lingua di traduzione preferita per Gitblit |
| | | gb.emailMeOnMyTicketChanges = Inviami una email quando uno dei miei ticket è modificato |
| | | gb.emailMeOnMyTicketChangesDescription = Inviami una email quando io stesso modifico un ticket |
| | | gb.displayNameDescription = Nome visualizzato |
| | | gb.emailAddressDescription = Indirizzo email principale per la ricezione delle notifiche |
| | | gb.sshKeys = Chiavi SSH |
| | | gb.sshKeysDescription = Autenticazione tramite chiave pubblica SSH è una alternativa sicura all'autenticazione tramite password |
| | | gb.addSshKey = Aggiungi una chiave SSH |
| | | gb.key = Chiave |
| | | gb.comment = 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 |
| | | gb.transportPreference = Preferenze di trasporto |
| | | gb.transportPreferenceDescription = Specifica il protocollo di trasporto che preferisci usare per le operazioni di clone |
| | | |
| | |
| | | gb.mergeToDescription = \ud2f0\ucf13 \ud328\uce58\uc14b\uc744 \uba38\uc9c0\ud560 \uae30\ubcf8 \ud1b5\ud569 \ube0c\ub79c\uce58 |
| | | gb.anonymousCanNotPropose = \uc775\uba85 \uc0ac\uc6a9\uc790\ub294 \ud328\uce58\uc14b\uc744 \uc81c\uc548\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. |
| | | gb.youDoNotHaveClonePermission = \ub2f9\uc2e0\uc740 \uc774 \uc800\uc7a5\uc18c\ub97c \ud074\ub860\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. |
| | | gb.myTickets = \ub0b4 \ud2f0\ucf13 |
| | | gb.yourAssignedTickets = \ub098\uc5d0\uac8c \ud560\ub2f9\ub41c |
| | | gb.newMilestone = \uc0c8 \ub9c8\uc77c\uc2a4\ud1a4 |
| | | gb.editMilestone = \ub9c8\uc77c\uc2a4\ud1a4 \uc218\uc815 |
| | | gb.deleteMilestone = \ub9c8\uc77c\uc2a4\ud1a4 \"{0}\"\uc744(\ub97c) \uc0ad\uc81c\ud560\uae4c\uc694? |
| | | gb.milestoneDeleteFailed = \ub9c8\uc77c\uc2a4\ud1a4 ''{0}'' \uc0ad\uc81c \uc2e4\ud328! |
| | | gb.notifyChangedOpenTickets = \uc5f0 \ud2f0\ucf13\uc758 \ubcc0\uacbd \uc54c\ub9bc \uc804\uc1a1 |
| | | gb.overdue = \uc9c0\uc5f0 |
| | | gb.openMilestones = \ub9c8\uc77c\uc2a4\ud1a4 \uc5f4\uae30 |
| | | gb.closedMilestones = \ub2eb\ud78c \ub9c8\uc77c\uc2a4\ud1a4 |
| | | gb.administration = \uad00\ub9ac |
| | | gb.plugins = \ud50c\ub7ec\uadf8\uc778 |
| | | gb.extensions = \ud655\uc7a5\uae30\ub2a5 |
| | | gb.pleaseSelectProject = \ud504\ub85c\uc81d\ud2b8\ub97c \uc120\ud0dd\ud574 \uc8fc\uc138\uc694! |
| | | gb.accessPolicy = \uc811\uadfc \uc815\ucc45 |
| | | gb.accessPolicyDescription = \uc800\uc7a5\uc18c \ubcf4\uae30\uc640 git \uad8c\ud55c\uc744 \uc81c\uc5b4\ud558\uae30 \uc704\ud574 \uc811\uadfc \uc815\ucc45\uc744 \uc120\ud0dd\ud558\uc138\uc694. |
| | | gb.anonymousPolicy = \uc775\uba85 \ubcf4\uae30, \ud074\ub860 \uadf8\ub9ac\uace0 \ud478\uc2dc |
| | | gb.anonymousPolicyDescription = \ub204\uad6c\ub098 \uc774 \uc800\uc7a5\uc18c\ub97c \ubcf4\uae30, \ud074\ub860, \uadf8\ub9ac\uace0 \ud478\uc2dc\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. |
| | | gb.authenticatedPushPolicy = \uc81c\ud55c\ub41c \ud478\uc2dc (\uc778\uc99d\ub41c) |
| | | gb.authenticatedPushPolicyDescription = \ub204\uad6c\ub098 \uc774 \uc800\uc7a5\uc18c\ub97c \ubcf4\uac70\ub098 \ud074\ub860\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ubaa8\ub4e0 \uc778\uc99d\ub41c \uc720\uc800\ub294 RW+ \ud478\uc2dc \uad8c\ud55c\uc744 \uac00\uc9d1\ub2c8\ub2e4. |
| | | gb.namedPushPolicy = \uc774\ub984\uc73c\ub85c \ud478\uc2dc \uc81c\ud55c |
| | | gb.namedPushPolicyDescription = \ub204\uad6c\ub098 \uc774 \uc800\uc7a5\uc18c\ub97c \ubcf4\uac70\ub098 \ud074\ub860\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc120\ud0dd\ud55c \uc720\uc800\ub9cc \ud478\uc2dc\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. |
| | | gb.clonePolicy = \uc81c\ud55c\ub41c \ud074\ub860 & \ud478\uc2dc |
| | | gb.clonePolicyDescription = \ub204\uad6c\ub098 \uc774 \uc800\uc7a5\uc18c\ub97c \ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc120\ud0dd\ud55c \uc720\uc800\ub9cc \ud074\ub860\uacfc \ud478\uc2dc\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. |
| | | gb.viewPolicy = \uc81c\ud55c\ub41c \ubcf4\uae30, \ud074\ub860 & \ud478\uc2dc |
| | | gb.viewPolicyDescription = \uc120\ud0dd\ud55c \uc720\uc800\ub9cc \uc774 \uc800\uc7a5\uc18c\uc5d0 \ub300\ud574 \ubcf4\uae30, \ud074\ub860 \uadf8\ub9ac\uace0 \ud478\uc2dc \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. |
| | | gb.initialCommit = \ucd5c\ucd08 \ucee4\ubc0b |
| | | gb.initialCommitDescription = \uc774 \uc800\uc7a5\uc18c\ub97c \uc989\uc2dc <code>git clone</code> \ud560 \uc218 \uc788\ub3c4\ub85d \ud569\ub2c8\ub2e4. \ub85c\uceec\uc5d0\uc11c <code>git init</code> \ud588\ub2e4\uba74 \uc774 \ub2e8\uacc4\ub97c \uac74\ub108\ub6f0\uc138\uc694. |
| | | gb.initWithReadme = README \ud3ec\ud568 |
| | | gb.initWithReadmeDescription = \uc800\uc7a5\uc18c\uc758 \uac04\ub2e8\ud55c README \ubb38\uc11c\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4. |
| | | gb.initWithGitignore = .gitignore \ud30c\uc77c \ud3ec\ud568 |
| | | gb.initWithGitignoreDescription = Git \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc815\uc758\ub41c \ud328\ud134\uc5d0 \ub530\ub77c \ud30c\uc77c\uc774\ub098 \ub514\ub809\ud1a0\ub9ac\ub97c \ubb34\uc2dc\ud558\ub3c4\ub85d \uc9c0\uc815\ud55c \uc124\uc815\ud30c\uc77c\uc744 \ucd94\uac00\ud569\ub2c8\ub2e4. |
| | | gb.pleaseSelectGitIgnore = .gitignore \ud30c\uc77c\uc744 \uc120\ud0dd\ud558\uc138\uc694. |
| | | gb.receive = \uc218\uc2e0 |
| | | gb.permissions = \uad8c\ud55c |
| | | gb.ownersDescription = \uc18c\uc720\uc790\ub294 \uc800\uc7a5\uc18c\uc758 \ubaa8\ub4e0 \uc124\uc815\uc744 \uad00\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uadf8\ub7ec\ub098, \uac1c\uc778 \uc800\uc7a5\uc18c\ub97c \uc81c\uc678\ud558\uace0\ub294 \uc800\uc7a5\uc18c \uc774\ub984\uc744 \ubcc0\uacbd\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. |
| | | gb.userPermissionsDescription = \uac1c\ubcc4 \uc0ac\uc6a9\uc790 \uad8c\ud55c\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774 \uc124\uc815\uc740 \ud300\uc774\ub098 \uc815\uaddc\uc2dd \uad8c\ud55c\uc744 \ubb34\uc2dc\ud569\ub2c8\ub2e4. |
| | | gb.teamPermissionsDescription = \uac1c\ubcc4 \ud300 \uad8c\ud55c\uc744 \uc9c0\uc815\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc774 \uc124\uc815\uc740 \uc815\uaddc\uc2dd \uad8c\ud55c\uc744 \ubb34\uc2dc\ud569\ub2c8\ub2e4. |
| | | gb.ticketSettings = \ud2f0\ucf13 \uc124\uc815 |
| | | gb.receiveSettings = \uc218\uc2e0 \uc124\uc815 |
| | | gb.receiveSettingsDescription = \uc218\uc2e0 \uc124\uc815\uc740 \uc800\uc7a5\uc18c\uc5d0 \ud478\uc2dc\ud558\ub294 \uac83\uc744 \uc81c\uc5b4\ud569\ub2c8\ub2e4. |
| | | gb.preReceiveDescription = Pre-receive \ud6c5\uc740 \ucee4\ubc0b\uc744 \uc218\uc2e0\ud588\uc9c0\ub9cc, refs \uac00 \uc5c5\ub370\uc774\ud2b8 \ub418\uae30 <em>\uc804</em> \uc5d0 \uc2e4\ud589\ub429\ub2c8\ub2e4.<p>\uc774\uac83\uc740 \ud478\uc2dc\ub97c \uac70\ubd80\ud558\uae30\uc5d0 \uc801\uc808\ud55c \ud6c5 \uc785\ub2c8\ub2e4.</p> |
| | | gb.postReceiveDescription = Post-receive \ud639\uc740 \ucee4\ubc0b\uc744 \uc218\uc2e0\ud558\uace0, refs \uac00 \uc5c5\ub370\uc774\ud2b8 \ub41c <em>\ud6c4</em> \uc5d0 \uc2e4\ud589\ub429\ub2c8\ub2e4.<p>\uc774\uac83\uc740 \uc54c\ub9bc, \ube4c\ub4dc \ud2b8\ub9ac\uac70 \ub4f1\uc744 \ud558\uae30\uc5d0 \uc801\uc808\ud55c \ud6c5 \uc785\ub2c8\ub2e4.</p> |
| | | gb.federationStrategyDescription = \ub2e4\ub978 Gitblit \uacfc \ud398\ub354\ub808\uc774\uc158 \ud558\ub294 \ubc29\ubc95\uc744 \uc81c\uc5b4\ud569\ub2c8\ub2e4. |
| | | gb.federationSetsDescription = \uc774 \uc800\uc7a5\uc18c\ub294 \uc120\ud0dd\ub41c \ud398\ub354\ub808\uc774\uc158 \uc14b\uc5d0 \ud3ec\ud568\ub429\ub2c8\ub2e4. |
| | | gb.miscellaneous = \uae30\ud0c0 |
| | | gb.originDescription = \uc774 \uc800\uc7a5\uc18c\uac00 \ud074\ub860\ub41c \uacf3\uc758 url |
| | | gb.gc = GC |
| | | gb.garbageCollection = \uac00\ube44\uc9c0 \uceec\ub809\uc158 |
| | | 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.commitMessageRendererDescription = \ucee4\ubc0b \uba54\uc2dc\uc9c0\ub294 \ud3c9\ubb38 \ub610\ub294 \ub9c8\ud06c\uc5c5\uc73c\ub85c \ub80c\ub354\ub9c1\ud558\uc5ec \ud45c\uc2dc\ub420 \uc218 \uc788\uc2b5\ub2c8\ub2e4. |
| | | gb.preferences = \uc124\uc815 |
| | | gb.accountPreferences = \uacc4\uc815 \uc124\uc815 |
| | | gb.accountPreferencesDescription = \uacc4\uc815 \uc124\uc815\uc744 \uc9c0\uc815\ud569\ub2c8\ub2e4. |
| | | gb.languagePreference = \uc5b8\uc5b4 \uc124\uc815 |
| | | gb.languagePreferenceDescription = \uc120\ud638\ud558\ub294 \uc5b8\uc5b4\ub97c \uc120\ud0dd\ud558\uc138\uc694. |
| | | gb.emailMeOnMyTicketChanges = \ub0b4 \ud2f0\ucf13\uc774 \ubcc0\uacbd\ub418\uba74 \uc774\uba54\uc77c\ub85c \uc54c\ub9bc |
| | | gb.emailMeOnMyTicketChangesDescription = \ub0b4\uac00 \ub9cc\ub4e0 \ud2f0\ucf13\uc758 \ubcc0\uacbd\ub418\uba74 \ubcc0\uacbd\uc0ac\ud56d\uc744 \ub098\uc758 \uc774\uba54\uc77c\ub85c \uc54c\ub824\uc90c |
| | | gb.displayNameDescription = \ud45c\uc2dc\ub420 \uc774\ub984 |
| | | gb.emailAddressDescription = \uc54c\ub9bc\uc744 \ubc1b\uae30\uc704\ud55c \uc8fc \uc774\uba54\uc77c |
| | | 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.addSshKey = SSH \ud0a4 \ucd94\uac00 |
| | | gb.key = \ud0a4 |
| | | gb.comment = \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. |
| | | gb.transportPreference = \uc804\uc1a1 \uc124\uc815 |
| | | gb.transportPreferenceDescription = \ud074\ub860\uc2dc \uc0ac\uc6a9\ud560 \uc124\uc815\uc744 \uc9c0\uc815\ud558\uc138\uc694. |
| | |
| | | gb.queryHelp = Standaard query syntax wordt ondersteund.<p/><p/>Zie aub <a target="_new" href="http://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/queryparsersyntax.html">Lucene Query Parser Syntax</a> voor informatie. |
| | | gb.queryResults = resultaten {0} - {1} ({2} hits) |
| | | gb.noHits = geen hits |
| | | gb.authored = authored |
| | | gb.committed = committed |
| | | gb.authored = geschreven |
| | | gb.committed = gecommit |
| | | gb.indexedBranches = geïndexeerde branches |
| | | gb.indexedBranchesDescription = kies de branches voor opname in uw Lucene index |
| | | gb.noIndexedRepositoriesWarning = geen van uw repositories is geconfigureerd voor Lucene indexering |
| | |
| | | gb.proposedThisChange = stelde deze wijziging voor |
| | | gb.uploadedPatchsetN = uploade patchset {0} |
| | | gb.uploadedPatchsetNRevisionN = uploade patchset {0} revisie {1} |
| | | gb.mergedPatchset = merged patchset |
| | | gb.mergedPatchset = gemergede patchset |
| | | gb.commented = becommentarieerde |
| | | gb.noDescriptionGiven = geen omschrijving gegeven |
| | | gb.toBranch = naar {0} |
| | |
| | | gb.compareToN = vergelijk met {0} |
| | | gb.open = open |
| | | gb.closed = gesloten |
| | | gb.merged = merged |
| | | gb.merged = gemerged |
| | | gb.ticketPatchset = ticket {0}, patchset {1} |
| | | gb.patchsetMergeable = Deze patchset kan automatisch gemerged worden naar {0}. |
| | | gb.patchsetMergeableMore = Deze patchset mag ook gemerged worden naar {0} vanaf de command line. |
| | | gb.patchsetMergeableMore = Deze patchset mag ook gemerged worden naar {0} vanaf de commandline. |
| | | gb.patchsetAlreadyMerged = Deze patchset is gemerged naar {0}. |
| | | gb.patchsetNotMergeable = Deze patchset kan niet automatisch gemerged worden naar {0}. |
| | | gb.patchsetNotMergeableMore = Deze patchset moet gerebased of handmatig gemerged worden naar {0} om conflicten op te lossen. |
| | |
| | | gb.patchsetVetoedMore = Een reviewer heeft een veto uitgesproken over deze patchset. |
| | | gb.write = write |
| | | gb.comment = commentaar |
| | | gb.preview = preview |
| | | gb.preview = voorbeeld |
| | | gb.leaveComment = plaats een opmerking... |
| | | gb.showHideDetails = toon/verberg details |
| | | gb.acceptNewPatchsets = accepteer patchsets |
| | |
| | | gb.all = alle |
| | | gb.mergeBase = merge base |
| | | gb.checkout = checkout |
| | | gb.checkoutViaCommandLine = Checkout via command line |
| | | gb.checkoutViaCommandLine = Checkout via commandline |
| | | 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.checkoutStep2 = Check de patchset uit naar een nieuwe branch en review hem |
| | | gb.mergingViaCommandLine = Mergen via command line |
| | | gb.mergingViaCommandLineNote = Als u de merge knop niet wilt gebruiken of een automatische merge niet kan worden uitgevoerd kunt u een handmatige merge op de command line uitvoeren. |
| | | gb.mergingViaCommandLine = Mergen via commandline |
| | | gb.mergingViaCommandLineNote = Als u de merge knop niet wilt gebruiken of een automatische merge niet kan worden uitgevoerd kunt u een handmatige merge op de commandline uitvoeren. |
| | | gb.mergeStep1 = Check out een nieuwe branch voor het reviewen van wijzigingen \u2014 run deze vanuit uw eigen projectdirectorie |
| | | gb.mergeStep2 = Breng de voorgestelde wijzigingen in en review ze |
| | | gb.mergeStep3 = Merge de voorgestelde wijzigingen en update de server |
| | |
| | | gb.serverDoesNotAcceptPatchsets = Deze server accepteert geen patchsets. |
| | | gb.ticketIsClosed = Deze ticket is gesloten. |
| | | gb.mergeToDescription = default integratie branch voor het mergen van ticket patchsets |
| | | gb.anonymousCanNotPropose = Anonieme gebruikers kunnen geen patchsets voorstellen. |
| | | gb.youDoNotHaveClonePermission = U heeft geen rechten voor het clonen van deze repositorie. |
| | | ggb.myTickets = mijn tickets |
| | | gb.yourAssignedTickets = toegewezen aan mij |
| | | gb.newMilestone = nieuwe milestone |
| | | gb.editMilestone = wijzig milestone |
| | | gb.deleteMilestone = Verwijder milestone \"{0}\"? |
| | | gb.milestoneDeleteFailed = Milestone verwijdering ''{0}'' niet gelukt! |
| | | gb.notifyChangedOpenTickets = verstuur notificatie voor wijziging open tickets |
| | | gb.overdue = te laat |
| | | gb.openMilestones = open milestones |
| | | gb.closedMilestones = gesloten milestones |
| | | gb.administration = administratie |
| | | gb.plugins = plugins |
| | | gb.extensions = extensies |
| | | gb.pleaseSelectProject = Kies aub het project! |
| | | gb.accessPolicy = Toegangspolicy |
| | | gb.accessPolicyDescription = Kies een toegangspolicy voor het managen van de zichtbaarheid van de repositorie en de git toegangsrechten. |
| | | gb.anonymousPolicy = Anoniem View, Clone, & Push |
| | | gb.anonymousPolicyDescription = Iedereen mag deze repositorie zien, clonen, en er naartoe pushen. |
| | | gb.authenticatedPushPolicy = Beperk Push (Geauthenticeerd) |
| | | gb.authenticatedPushPolicyDescription = Iedereen kan deze repositorie zien en clonen. Alle geauthenticeerde gebruikers hebben RW+ push permissie. |
| | | gb.namedPushPolicy = Beperk Push (Gebruiker bekend) |
| | | gb.namedPushPolicyDescription = Iedereen kan deze repositorie zien en clonen. U bepaalt wie er mag pushen. |
| | | gb.clonePolicy = Beperk Clone & Push |
| | | gb.clonePolicyDescription = Iedereen kan deze repositorie zien. U bepaalt wie er mag clonen en pushen. |
| | | gb.viewPolicy = Beperk Zien, Clonen en Push |
| | | gb.viewPolicyDescription = U bepaalt wie deze repositorie mag zien, clonen en er naar toe pushen. |
| | | gb.initialCommit = Initiele Commit |
| | | gb.initialCommitDescription = Dit maakt het u mogelijk om meteen <code>git clone</code> deze repositorie. Sla deze stap over als u al <code>git init</code> lokaal heeft uitgevoerd. |
| | | gb.initWithReadme = Voeg een README toe |
| | | gb.initWithReadmeDescription = Dit zal een eenvoudige README document toevoegen aan uw repositorie. |
| | | gb.initWithGitignore = Voeg een .gitignore bestand toe |
| | | gb.initWithGitignoreDescription = Dit zal een configuratiebestand toevoegen dat uw Git programma zal instrueren om bepaalde bestanden of directories die aan bepaalde selectiepatronen voldoen te negeren. |
| | | gb.pleaseSelectGitIgnore = Kies aub een .gitignore bestand |
| | | gb.receive = ontvang |
| | | gb.permissions = permissies |
| | | gb.ownersDescription = Eigenaren kunnen alle repositoriesettings managen maar het is niet toegestaan een repositorie te hernoemen tenzij het hun persoonlijke repositorie is. |
| | | gb.userPermissionsDescription = U kunt afzonderlijke gebruikerspermissies specificeren. Deze instellingen zullen team- of regexpermisies overrulen. |
| | | gb.teamPermissionsDescription = U kunt afzonderlijke teamspermissies specificeren. Deze instellingen zullen regexpermisies overrulen. |
| | | gb.ticketSettings = Ticket Instellingen |
| | | gb.receiveSettings = Ontvangstinstellingen |
| | | gb.receiveSettingsDescription = De Ontvangstinstellingen managen pushes naar de repositorie. |
| | | gb.preReceiveDescription = Pre-receive hooks worden uitgevoerd na commits zijn ontvangen maar <em>VOORDAT</em> de refs worden geupdated.<p>Dit is de juiste hook voor het afwijzen van een push.</p> |
| | | gb.postReceiveDescription = Post-receive hooks worden uitgevoerd na commits zijn ontvangen maar <em>NADAT</em> de refs zijn geupdated.<p>Dit is de juiste hook voor notificaties, build triggers, etc.</p> |
| | | gb.federationStrategyDescription = Bepaal of en hoe deze repositorie te federeren met een andere Gitblit. |
| | | gb.federationSetsDescription = Deze repository zal worden opgenomen in de geselecteerde federatie sets. |
| | | gb.miscellaneous = diversen |
| | | gb.originDescription = De url vanaf welke deze repositorie was gecloned. |
| | | gb.gc = GC |
| | | gb.garbageCollection = Garbage Collection |
| | | gb.garbageCollectionDescription = De garbage collector zal losse objecten die gepushed zijn van clients samenvoegen en zal ongereferentieerde objecten uit de repository verwijderen. |
| | | gb.commitMessageRendererDescription = Commit meldingen kunnen worden getoond als platte tekst of als gerenderde markup. |
| | | gb.preferences = voorkeuren |
| | | gb.accountPreferences = Accountvoorkeuren |
| | | gb.accountPreferencesDescription = Specificeer uw accountvoorkeuren |
| | | gb.languagePreference = Taalvoorkeuren |
| | | gb.languagePreferenceDescription = Selecteer uw voorkeursvertaling van voor Gitblit |
| | | gb.emailMeOnMyTicketChanges = Email bij ticketwijziging |
| | | gb.emailMeOnMyTicketChangesDescription = Stuur me een emailnotificatie voor wijzigingen die ik aanbreng aan een ticket |
| | | gb.displayNameDescription = De gewenste naam om te tonen |
| | | gb.emailAddressDescription = Het primaire emailadres voor het ontvangen van notificaties |
| | | gb.sshKeys = SSH Sleutels |
| | | gb.sshKeysDescription = SSH publiekesleutelauthenticatie is een veilig alternatief voor wachtwoordauthenticatie |
| | | gb.addSshKey = Voeg SSH Sleutel toe |
| | | gb.key = Sleutel |
| | | gb.comment = 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 |
| | |
| | | gb.commitActivityTrend = aktivitetstrend for commits |
| | | gb.commitActivityDOW = commit aktivitet gruppert p\u00e5 ukedag |
| | | gb.commitActivityAuthors = prim\u00e6rforfattere etter aktivitet |
| | | gb.feed = feed |
| | | gb.cancel = avbryt |
| | | gb.changePassword = endre passord |
| | | gb.isFederated = er federert |
| | | gb.federateThis = federer dette repositoriet |
| | | gb.federateOrigin = federere origin |
| | |
| | | gb.mergeToDescription = standard integration branch for merging av ticket patchsett |
| | | gb.anonymousCanNotPropose = Anonyme brukere kan ikke foresl\u00e5 patchsett |
| | | gb.youDoNotHaveClonePermission = Du har ikke tillatelse til \u00e5 klone dette repositoriet. |
| | | gb.myTickets = mine tickets |
| | | gb.yourAssignedTickets = tilordnet deg |
| | | gb.newMilestone = ny milep\u00e6l |
| | | gb.editMilestone = endre milep\u00e6l |
| | | gb.deleteMilestone = Slette milep\u00e6l \"{0}\"? |
| | | gb.milestoneDeleteFailed = Greide ikke å slette milep\u00e6l ''{0}''! |
| | | gb.notifyChangedOpenTickets = send meldin om endrede \u00e5pne tickets |
| | | gb.overdue = forfalt |
| | | gb.openMilestones = \u00e5pne milep\u00e6ler |
| | | gb.closedMilestones = lukkede milep\u00e6ler |
| | | gb.administration = administrasjon |
| | | gb.plugins = plugins |
| | | gb.extensions = extensions |
| | | gb.pleaseSelectProject = Vennligst velg prosjekt! |
| | | gb.accessPolicy = Tilgangspolicy |
| | | gb.accessPolicyDescription = Velg en tilgangspolicy for å kontrollere synlighet og tilganger. |
| | | gb.anonymousPolicy = Anonym view, clone og push |
| | | gb.anonymousPolicyDescription = Alle kan se, clone ofg pushe til dette repositoriet. |
| | | gb.authenticatedPushPolicy = Begrens push (Autentisert) |
| | | gb.authenticatedPushPolicyDescription = Alle kan se og klone dette repositoriet. Alle autentiserte brukere har lese og skrivetilgang. |
| | | gb.namedPushPolicy = Begrens push (navngitt) |
| | | 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.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.initWithReadme = Inkluder en README |
| | | gb.initWithReadmeDescription = Dette vil generere en enkel README-fil i ditt repository. |
| | | gb.initWithGitignore = Inkluder en .gitignore fil |
| | | gb.initWithGitignoreDescription = Dette vil inkludere en konfigurasjonsfil som instruerer git-klienter til å ignorerer filer og kataloger som matcher definerte m\u00F8nstre. |
| | | gb.pleaseSelectGitIgnore = Vennligst velg en .gitignore fil |
| | | gb.receive = motta |
| | | gb.permissions = rettigheter |
| | | gb.ownersDescription = Eiere kan administrere alle repositoriets innstillinger men de kan ikke endre p\u00e5 repositoriets navn med mindre det er deres eget repository. |
| | | gb.userPermissionsDescription = Du kan spesifisere individuelle brukerrettigheter. Disse innstillingene overstyrer team- eller regul\u00e6ruttrykk-baserte rettigheter. |
| | | gb.teamPermissionsDescription = Du kan spesifisere individuelle team-rettigheter. Disse innstillingene overstyrer regul\u00e6ruttrykk-baserte rettigheter.. |
| | | gb.ticketSettings = Ticket innstillinger |
| | | gb.receiveSettings = Innstillinger for mottak av push |
| | | gb.receiveSettingsDescription = Kontrollerer pushing til repositoriet. |
| | | gb.preReceiveDescription = Pre-receive hooks blir utf\u00F8rt etter en committ er mottatt men <em>F\u00D8</em> refs har blitt oppdatert.<p>Dette er det passende stedet \u00e5 avvise en push.</p> |
| | | gb.postReceiveDescription = Post-receive hooks blir utf\u00F8rt etter en committ er mottatt og <em>ETTER</em> refs har blitt oppdatert.<p>Dette er det passende stedet for notifikasjoner, build triggers osv.</p> |
| | | gb.federationStrategyDescription = Kontroller om og hvordan dette repositoriet skal federeres med en annen Gitblit instans. |
| | | gb.federationSetsDescription = Dette repositoriet vil bli inkludert i de valgte federeringssettene. |
| | | gb.miscellaneous = ymse |
| | | gb.originDescription = URL'en som dette repositoriet ble klonet fra. |
| | | gb.gc = GC |
| | | gb.garbageCollection = Garbage Collection |
| | | gb.garbageCollectionDescription = Garbage collectoren vil pakke sammen l\u00F8se objekter pushet fra klientene og fjerne objekter det ikke refereres til fra minnet. |
| | | gb.commitMessageRendererDescription = Commit-meldinger kan vises som ren tekst, eller som markup. |
| | | gb.preferences = innstillinger |
| | | gb.accountPreferences = Kontoinnstillinger |
| | | gb.accountPreferencesDescription = Velg dine kontoinnstillinger |
| | | gb.languagePreference = Foretrukket spr\u00e5k |
| | | gb.languagePreferenceDescription = Velg ditt foretrukne spr\u00e5k for Gitblit |
| | | gb.emailMeOnMyTicketChanges = Send meg en epost når ticketen min endrer seg |
| | | gb.emailMeOnMyTicketChangesDescription = Send meg en epost for endringer jeg gjør på en ticket. |
| | | gb.displayNameDescription = Foretrukket visningsnavn |
| | | gb.emailAddressDescription = Prim\u00e6r epostadresse for notifikasjoner |
| | | gb.sshKeys = SSH n\u00F8kler |
| | | gb.sshKeysDescription = SSH public key autentisering er et sikkert alternativ til autentisering med passord |
| | | gb.addSshKey = Legg til SSH n\u00F8kkel |
| | | gb.key = N\u00F8kkel |
| | | gb.comment = 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.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.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.overdue = \u8fc7\u671f |
| | | gb.openMilestones = \u5df2\u5f00\u542f milestones |
| | | gb.closedMilestones = \u5df2\u5173\u95ed milestones |
| | | gb.administration = \u7ba1\u7406 |
| | | gb.plugins = \u63d2\u4ef6 |
| | | gb.extensions = \u6269\u5c55 |
| | | 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.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.clonePolicy = \u9650\u5236\u514b\u9686\uff0c\u63a8\u9001 |
| | | 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.viewPolicy = \u9650\u5236\u67e5\u770b\uff0c\u514b\u9686\u548c\u63a8\u9001 |
| | | gb.viewPolicyDescription = \u60a8\u53ef\u4ee5\u9009\u62e9\u62e5\u6709\u67e5\u770b\uff0c\u514b\u9686\u548c\u63a8\u9001\u6743\u9650\u7684\u7528\u6237\u3002 |
| | | gb.initialCommit = \u521d\u59cb\u5316\u63d0\u4ea4 |
| | | gb.initialCommitDescription = \u6b64\u529f\u80fd\u76f8\u5f53\u4e8e\u76f4\u63a5\u5bf9\u5f53\u524d\u7248\u672c\u5e93\u8fdb\u884c <code>git clone</code> \u3002 \u5982\u679c\u8df3\u8fc7\u6b64\u6b65\uff0c\u60a8\u5fc5\u987b\u5728\u672c\u5730\u8fdb\u884c <code>git init</code> \u3002 |
| | | gb.initWithReadme = \u52a0\u5165 README |
| | | gb.initWithReadmeDescription = \u6b64\u529f\u80fd\u4f1a\u81ea\u52a8\u751f\u6210\u4e00\u4e2a\u60a8\u7684\u7248\u672c\u5e93\u7684 README \u6587\u4ef6\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.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.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.preferences = \u504f\u597d |
| | | gb.accountPreferences = \u7528\u6237\u504f\u597d |
| | | gb.accountPreferencesDescription = \u8bbe\u7f6e\u60a8\u7684\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.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 |
New file |
| | |
| | | package com.gitblit.wicket; |
| | | |
| | | import java.util.Date; |
| | | import java.util.TimeZone; |
| | | |
| | | import org.apache.wicket.markup.html.WebPage; |
| | | |
| | | import com.gitblit.IStoredSettings; |
| | | import com.gitblit.manager.IAuthenticationManager; |
| | | import com.gitblit.manager.IFederationManager; |
| | | import com.gitblit.manager.IGitblit; |
| | | import com.gitblit.manager.INotificationManager; |
| | | import com.gitblit.manager.IPluginManager; |
| | | import com.gitblit.manager.IProjectManager; |
| | | import com.gitblit.manager.IRepositoryManager; |
| | | import com.gitblit.manager.IRuntimeManager; |
| | | import com.gitblit.manager.IUserManager; |
| | | import com.gitblit.tickets.ITicketService; |
| | | import com.gitblit.transport.ssh.IPublicKeyManager; |
| | | |
| | | public interface GitblitWicketApp { |
| | | |
| | | public abstract void mount(String location, Class<? extends WebPage> clazz, String... parameters); |
| | | |
| | | public abstract Class<? extends WebPage> getHomePage(); |
| | | |
| | | public abstract boolean isCacheablePage(String mountPoint); |
| | | |
| | | public abstract CacheControl getCacheControl(String mountPoint); |
| | | |
| | | public abstract IStoredSettings settings(); |
| | | |
| | | /** |
| | | * Is Gitblit running in debug mode? |
| | | * |
| | | * @return true if Gitblit is running in debug mode |
| | | */ |
| | | public abstract boolean isDebugMode(); |
| | | |
| | | /* |
| | | * These methods look strange... and they are... but they are the first |
| | | * step towards modularization across multiple commits. |
| | | */ |
| | | public abstract Date getBootDate(); |
| | | |
| | | public abstract Date getLastActivityDate(); |
| | | |
| | | public abstract IRuntimeManager runtime(); |
| | | |
| | | public abstract IPluginManager plugins(); |
| | | |
| | | public abstract INotificationManager notifier(); |
| | | |
| | | public abstract IUserManager users(); |
| | | |
| | | public abstract IAuthenticationManager authentication(); |
| | | |
| | | public abstract IPublicKeyManager keys(); |
| | | |
| | | public abstract IRepositoryManager repositories(); |
| | | |
| | | public abstract IProjectManager projects(); |
| | | |
| | | public abstract IFederationManager federation(); |
| | | |
| | | public abstract IGitblit gitblit(); |
| | | |
| | | public abstract ITicketService tickets(); |
| | | |
| | | public abstract TimeZone getTimezone(); |
| | | |
| | | } |
| | |
| | | import com.gitblit.IStoredSettings;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.PathModel;
|
| | | import com.gitblit.servlet.RawServlet;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.MarkdownUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.pages.DocPage;
|
| | | import com.gitblit.wicket.pages.RawPage;
|
| | | import com.google.common.base.Joiner;
|
| | |
|
| | | /**
|
| | |
| | | if (imagePath.indexOf("://") == -1) {
|
| | | // relative image
|
| | | String path = doc.getRelativePath(imagePath);
|
| | | url = getWicketUrl(RawPage.class, repositoryName, commitId, path);
|
| | | String contextUrl = RequestCycle.get().getRequest().getRelativePathPrefixToContextRoot();
|
| | | url = RawServlet.asLink(contextUrl, repositoryName, commitId, path);
|
| | | } else {
|
| | | // absolute image
|
| | | url = imagePath;
|
| | |
| | | if (node.url.indexOf("://") == -1) {
|
| | | // repository-relative image link
|
| | | String path = doc.getRelativePath(node.url);
|
| | | String url = getWicketUrl(RawPage.class, repositoryName, commitId, path);
|
| | | String contextUrl = RequestCycle.get().getRequest().getRelativePathPrefixToContextRoot();
|
| | | String url = RawServlet.asLink(contextUrl, repositoryName, commitId, path);
|
| | | return new Rendering(url, text);
|
| | | }
|
| | | // absolute image link
|
| | |
| | | if (url.indexOf("://") == -1) {
|
| | | // repository-relative image link
|
| | | String path = doc.getRelativePath(url);
|
| | | String wurl = getWicketUrl(RawPage.class, repositoryName, commitId, path);
|
| | | String contextUrl = RequestCycle.get().getRequest().getRelativePathPrefixToContextRoot();
|
| | | String wurl = RawServlet.asLink(contextUrl, repositoryName, commitId, path);
|
| | | rendering = new Rendering(wurl, alt);
|
| | | } else {
|
| | | // absolute image link
|
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.wicket; |
| | | |
| | | import java.io.IOException; |
| | | import java.net.URL; |
| | | import java.util.Enumeration; |
| | | import java.util.HashSet; |
| | | import java.util.Iterator; |
| | | import java.util.Set; |
| | | import java.util.TreeSet; |
| | | |
| | | import org.apache.wicket.WicketRuntimeException; |
| | | import org.apache.wicket.application.IClassResolver; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import ro.fortsoft.pf4j.PluginState; |
| | | import ro.fortsoft.pf4j.PluginWrapper; |
| | | |
| | | import com.gitblit.manager.IPluginManager; |
| | | |
| | | /** |
| | | * Resolves plugin classes and resources. |
| | | */ |
| | | public class PluginClassResolver implements IClassResolver { |
| | | private static final Logger logger = LoggerFactory.getLogger(PluginClassResolver.class); |
| | | |
| | | private final IClassResolver coreResolver; |
| | | private final IPluginManager pluginManager; |
| | | |
| | | public PluginClassResolver(IClassResolver coreResolver, IPluginManager pluginManager) { |
| | | this.coreResolver = coreResolver; |
| | | this.pluginManager = pluginManager; |
| | | } |
| | | |
| | | @Override |
| | | public Class<?> resolveClass(final String className) throws ClassNotFoundException { |
| | | boolean debugEnabled = logger.isDebugEnabled(); |
| | | |
| | | for (PluginWrapper plugin : pluginManager.getPlugins()) { |
| | | if (PluginState.STARTED != plugin.getPluginState()) { |
| | | // ignore this plugin |
| | | continue; |
| | | } |
| | | |
| | | try { |
| | | return plugin.getPluginClassLoader().loadClass(className); |
| | | } catch (ClassNotFoundException cnfx) { |
| | | if (debugEnabled) { |
| | | logger.debug("ClassResolver '{}' cannot find class: '{}'", plugin.getPluginId(), className); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return coreResolver.resolveClass(className); |
| | | } |
| | | |
| | | @Override |
| | | public Iterator<URL> getResources(final String name) { |
| | | Set<URL> urls = new TreeSet<URL>(new UrlExternalFormComparator()); |
| | | |
| | | for (PluginWrapper plugin : pluginManager.getPlugins()) { |
| | | if (PluginState.STARTED != plugin.getPluginState()) { |
| | | // ignore this plugin |
| | | continue; |
| | | } |
| | | |
| | | Iterator<URL> it = getResources(name, plugin); |
| | | while (it.hasNext()) { |
| | | URL url = it.next(); |
| | | urls.add(url); |
| | | } |
| | | } |
| | | |
| | | Iterator<URL> it = coreResolver.getResources(name); |
| | | while (it.hasNext()) { |
| | | URL url = it.next(); |
| | | urls.add(url); |
| | | } |
| | | return urls.iterator(); |
| | | } |
| | | |
| | | protected Iterator<URL> getResources(String name, PluginWrapper plugin) { |
| | | HashSet<URL> loadedFiles = new HashSet<URL>(); |
| | | try { |
| | | // Try the classloader for the wicket jar/bundle |
| | | Enumeration<URL> resources = plugin.getPluginClassLoader().getResources(name); |
| | | loadResources(resources, loadedFiles); |
| | | } catch (IOException e) { |
| | | throw new WicketRuntimeException(e); |
| | | } |
| | | |
| | | return loadedFiles.iterator(); |
| | | } |
| | | |
| | | private void loadResources(Enumeration<URL> resources, Set<URL> loadedFiles) { |
| | | if (resources != null) { |
| | | while (resources.hasMoreElements()) { |
| | | final URL url = resources.nextElement(); |
| | | if (!loadedFiles.contains(url)) { |
| | | loadedFiles.add(url); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | import org.apache.wicket.markup.ComponentTag; |
| | | import org.apache.wicket.markup.MarkupStream; |
| | | import org.apache.wicket.markup.html.form.StatelessForm; |
| | | import org.apache.wicket.protocol.http.RequestUtils; |
| | | import org.apache.wicket.protocol.http.WicketURLDecoder; |
| | | import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy; |
| | | import org.apache.wicket.util.string.AppendingStringBuffer; |
| | |
| | | |
| | | private static final String HIDDEN_DIV_START = "<div style=\"width:0px;height:0px;position:absolute;left:-100px;top:-100px;overflow:hidden\">"; |
| | | |
| | | private final Class<? extends BasePage> pageClass; |
| | | protected final Class<? extends BasePage> pageClass; |
| | | |
| | | private final PageParameters pageParameters; |
| | | protected final PageParameters pageParameters; |
| | | |
| | | private final Logger log = LoggerFactory.getLogger(SessionlessForm.class); |
| | | |
| | |
| | | String un = WicketURLDecoder.QUERY_INSTANCE.decode(s); |
| | | return Strings.escapeMarkup(un).toString(); |
| | | } |
| | | |
| | | protected String getAbsoluteUrl() { |
| | | return getAbsoluteUrl(pageClass, pageParameters); |
| | | } |
| | | |
| | | protected String getAbsoluteUrl(Class<? extends BasePage> pageClass, PageParameters pageParameters) { |
| | | String relativeUrl = urlFor(pageClass, pageParameters).toString(); |
| | | String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl); |
| | | return absoluteUrl; |
| | | } |
| | | } |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.wicket; |
| | | |
| | | import java.io.Serializable; |
| | | import java.text.MessageFormat; |
| | | |
| | | import org.apache.wicket.markup.html.basic.Label; |
| | | |
| | | import com.gitblit.models.TicketModel; |
| | | import com.gitblit.models.TicketModel.Status; |
| | | import com.gitblit.models.TicketModel.Type; |
| | | import com.gitblit.utils.StringUtils; |
| | | |
| | | /** |
| | | * Common tickets ui methods and classes. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public class TicketsUI { |
| | | |
| | | public static final String [] openStatii = new String [] { Status.New.name().toLowerCase(), Status.Open.name().toLowerCase() }; |
| | | |
| | | public static final String [] closedStatii = new String [] { "!" + Status.New.name().toLowerCase(), "!" + Status.Open.name().toLowerCase() }; |
| | | |
| | | public static Label getStateIcon(String wicketId, TicketModel ticket) { |
| | | return getStateIcon(wicketId, ticket.type, ticket.status); |
| | | } |
| | | |
| | | public static Label getStateIcon(String wicketId, Type type, Status state) { |
| | | Label label = new Label(wicketId); |
| | | if (type == null) { |
| | | type = Type.defaultType; |
| | | } |
| | | switch (type) { |
| | | case Proposal: |
| | | WicketUtils.setCssClass(label, "fa fa-code-fork"); |
| | | break; |
| | | case Bug: |
| | | WicketUtils.setCssClass(label, "fa fa-bug"); |
| | | break; |
| | | case Enhancement: |
| | | WicketUtils.setCssClass(label, "fa fa-magic"); |
| | | break; |
| | | case Question: |
| | | WicketUtils.setCssClass(label, "fa fa-question"); |
| | | break; |
| | | default: |
| | | // standard ticket |
| | | WicketUtils.setCssClass(label, "fa fa-ticket"); |
| | | } |
| | | WicketUtils.setHtmlTooltip(label, getTypeState(type, state)); |
| | | return label; |
| | | } |
| | | |
| | | public static String getTypeState(Type type, Status state) { |
| | | return state.toString() + " " + type.toString(); |
| | | } |
| | | |
| | | public static String getLozengeClass(Status status, boolean subtle) { |
| | | if (status == null) { |
| | | status = Status.New; |
| | | } |
| | | String css = ""; |
| | | switch (status) { |
| | | case Declined: |
| | | case Duplicate: |
| | | case Invalid: |
| | | case Wontfix: |
| | | case Abandoned: |
| | | css = "aui-lozenge-error"; |
| | | break; |
| | | case Fixed: |
| | | case Merged: |
| | | case Resolved: |
| | | css = "aui-lozenge-success"; |
| | | break; |
| | | case New: |
| | | css = "aui-lozenge-complete"; |
| | | break; |
| | | case On_Hold: |
| | | css = "aui-lozenge-current"; |
| | | break; |
| | | default: |
| | | css = ""; |
| | | break; |
| | | } |
| | | |
| | | return "aui-lozenge" + (subtle ? " aui-lozenge-subtle": "") + (css.isEmpty() ? "" : " ") + css; |
| | | } |
| | | |
| | | public static String getStatusClass(Status status) { |
| | | String css = ""; |
| | | switch (status) { |
| | | case Declined: |
| | | case Duplicate: |
| | | case Invalid: |
| | | case Wontfix: |
| | | case Abandoned: |
| | | css = "resolution-error"; |
| | | break; |
| | | case Fixed: |
| | | case Merged: |
| | | case Resolved: |
| | | css = "resolution-success"; |
| | | break; |
| | | case New: |
| | | css = "resolution-complete"; |
| | | break; |
| | | case On_Hold: |
| | | css = "resolution-current"; |
| | | break; |
| | | default: |
| | | css = ""; |
| | | break; |
| | | } |
| | | |
| | | return "resolution" + (css.isEmpty() ? "" : " ") + css; |
| | | } |
| | | |
| | | public static class TicketSort implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public final String name; |
| | | public final String sortBy; |
| | | public final boolean desc; |
| | | |
| | | public TicketSort(String name, String sortBy, boolean desc) { |
| | | this.name = name; |
| | | this.sortBy = sortBy; |
| | | this.desc = desc; |
| | | } |
| | | } |
| | | |
| | | public static class Indicator implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public final String css; |
| | | public final int count; |
| | | public final String tooltip; |
| | | |
| | | public Indicator(String css, String tooltip) { |
| | | this.css = css; |
| | | this.tooltip = tooltip; |
| | | this.count = 0; |
| | | } |
| | | |
| | | public Indicator(String css, int count, String pattern) { |
| | | this.css = css; |
| | | this.count = count; |
| | | this.tooltip = StringUtils.isEmpty(pattern) ? "" : MessageFormat.format(pattern, count); |
| | | } |
| | | |
| | | public String getTooltip() { |
| | | return tooltip; |
| | | } |
| | | } |
| | | |
| | | public static class TicketQuery implements Serializable, Comparable<TicketQuery> { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public final String name; |
| | | public final String query; |
| | | public String color; |
| | | |
| | | public TicketQuery(String name, String query) { |
| | | this.name = name; |
| | | this.query = query; |
| | | } |
| | | |
| | | public TicketQuery color(String value) { |
| | | this.color = value; |
| | | return this; |
| | | } |
| | | |
| | | @Override |
| | | public boolean equals(Object o) { |
| | | if (o instanceof TicketQuery) { |
| | | return ((TicketQuery) o).query.equals(query); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() { |
| | | return query.hashCode(); |
| | | } |
| | | |
| | | @Override |
| | | public int compareTo(TicketQuery o) { |
| | | return query.compareTo(o.query); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | /* |
| | | * Licensed to the Apache Software Foundation (ASF) under one or more |
| | | * contributor license agreements. See the NOTICE file distributed with |
| | | * this work for additional information regarding copyright ownership. |
| | | * The ASF licenses this file to You 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.wicket; |
| | | |
| | | import java.net.URL; |
| | | import java.util.Comparator; |
| | | |
| | | /** |
| | | * A comparator of URL instances. |
| | | * |
| | | * Comparing URLs with their implementation of #equals() is |
| | | * bad because it may cause problems like DNS resolving, or other |
| | | * slow checks. This comparator uses the external form of an URL |
| | | * to make a simple comparison of two Strings. |
| | | * |
| | | * @since 1.5.6 |
| | | */ |
| | | public class UrlExternalFormComparator implements Comparator<URL> |
| | | { |
| | | @Override |
| | | public int compare(URL url1, URL url2) |
| | | { |
| | | return url1.toExternalForm().compareTo(url2.toExternalForm()); |
| | | } |
| | | } |
| | |
| | |
|
| | | public static PageParameters newRepositoryParameter(String repositoryName) {
|
| | | Map<String, String> parameterMap = new HashMap<String, String>();
|
| | | parameterMap.put("r", repositoryName);
|
| | | if (!StringUtils.isEmpty(repositoryName)) {
|
| | | parameterMap.put("r", repositoryName);
|
| | | }
|
| | | return new PageParameters(parameterMap);
|
| | | }
|
| | |
|
| | |
| | | return new PageParameters(parameterMap);
|
| | | }
|
| | |
|
| | | public static PageParameters newTicketsParameters(String repositoryName, String... states) {
|
| | | PageParameters tParams = newRepositoryParameter(repositoryName);
|
| | | if (states != null) {
|
| | | for (String state : states) {
|
| | | tParams.add("status", state);
|
| | | }
|
| | | }
|
| | | return tParams;
|
| | | }
|
| | |
|
| | | public static PageParameters newOpenTicketsParameter(String repositoryName) {
|
| | | return newTicketsParameters(repositoryName, TicketsUI.openStatii);
|
| | | }
|
| | |
|
| | | public static String getProjectName(PageParameters params) {
|
| | | return params.getString("p", "");
|
| | | }
|
| | |
| | |
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.Activity;
|
| | | import com.gitblit.models.Menu.ParameterMenuItem;
|
| | | import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
|
| | | import com.gitblit.models.Metric;
|
| | | import com.gitblit.models.NavLink;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.utils.ActivityUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.CacheControl;
|
| | | import com.gitblit.wicket.CacheControl.LastModified;
|
| | | import com.gitblit.wicket.PageRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.charting.Chart;
|
| | | import com.gitblit.wicket.charting.Charts;
|
| | |
| | | }
|
| | |
|
| | | @Override
|
| | | protected void addDropDownMenus(List<PageRegistration> pages) {
|
| | | DropDownMenuRegistration filters = new DropDownMenuRegistration("gb.filters",
|
| | | protected void addDropDownMenus(List<NavLink> navLinks) {
|
| | | DropDownPageMenuNavLink filters = new DropDownPageMenuNavLink("gb.filters",
|
| | | ActivityPage.class);
|
| | |
|
| | | PageParameters currentParameters = getPageParameters();
|
| | |
| | |
|
| | | if (filters.menuItems.size() > 0) {
|
| | | // Reset Filter
|
| | | filters.menuItems.add(new DropDownMenuItem(getString("gb.reset"), null, null));
|
| | | filters.menuItems.add(new ParameterMenuItem(getString("gb.reset")));
|
| | | }
|
| | | pages.add(filters);
|
| | | navLinks.add(filters);
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | }
|
| | | charts.addChart(chart);
|
| | |
|
| | | // active repositories pie chart |
| | | // active repositories pie chart
|
| | | chart = charts.createPieChart("chartRepositories", getString("gb.activeRepositories"),
|
| | | getString("gb.repository"), getString("gb.commits"));
|
| | | for (Metric metric : repositoryMetrics.values()) {
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | protected String getContextUrl() {
|
| | | return getRequest().getRelativePathPrefixToContextRoot();
|
| | | }
|
| | |
|
| | | protected String getCanonicalUrl() {
|
| | | return getCanonicalUrl(getClass(), getPageParameters());
|
| | | }
|
| | |
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.image.Image;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | |
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.servlet.RawServlet;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.CacheControl;
|
| | |
| | | WicketUtils.newPathParameter(repositoryName, objectId, blobPath))
|
| | | .setEnabled(false));
|
| | | add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class).setEnabled(false));
|
| | | add(new BookmarkablePageLink<Void>("rawLink", RawPage.class,
|
| | | WicketUtils.newPathParameter(repositoryName, objectId, blobPath)));
|
| | | String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, objectId, blobPath);
|
| | | add(new ExternalLink("rawLink", rawUrl));
|
| | | add(new CommitHeaderPanel("commitHeader", objectId));
|
| | | add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, blobPath, objectId));
|
| | | Component c = new Label("blobText", JGitUtils.getStringContent(r, objectId, encodings));
|
| | |
| | | WicketUtils.newPathParameter(repositoryName, objectId, blobPath)));
|
| | | add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class,
|
| | | WicketUtils.newPathParameter(repositoryName, objectId, blobPath)));
|
| | | add(new BookmarkablePageLink<Void>("rawLink", RawPage.class,
|
| | | WicketUtils.newPathParameter(repositoryName, objectId, blobPath)));
|
| | | String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, objectId, blobPath);
|
| | | add(new ExternalLink("rawLink", rawUrl));
|
| | |
|
| | | add(new CommitHeaderPanel("commitHeader", repositoryName, commit));
|
| | |
|
| | |
| | | case 2:
|
| | | // image blobs
|
| | | add(new Label("blobText").setVisible(false));
|
| | | add(new ExternalImage("blobImage", urlFor(RawPage.class, WicketUtils.newPathParameter(repositoryName, objectId, blobPath)).toString()));
|
| | | add(new ExternalImage("blobImage", rawUrl));
|
| | | break;
|
| | | case 3:
|
| | | // binary blobs
|
| | |
| | | import com.gitblit.models.GitNote; |
| | | import com.gitblit.models.PathModel.PathChangeModel; |
| | | import com.gitblit.models.SubmoduleModel; |
| | | import com.gitblit.servlet.RawServlet; |
| | | import com.gitblit.utils.DiffUtils; |
| | | import com.gitblit.utils.DiffUtils.DiffOutput; |
| | | import com.gitblit.utils.DiffUtils.DiffOutputType; |
| | |
| | | item.add(new BookmarkablePageLink<Void>("view", BlobPage.class, WicketUtils |
| | | .newPathParameter(repositoryName, entry.commitId, entry.path)) |
| | | .setEnabled(!entry.changeType.equals(ChangeType.DELETE))); |
| | | item.add(new BookmarkablePageLink<Void>("raw", RawPage.class, WicketUtils |
| | | .newPathParameter(repositoryName, entry.commitId, entry.path)) |
| | | String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, entry.commitId, entry.path); |
| | | item.add(new ExternalLink("raw", rawUrl) |
| | | .setEnabled(!entry.changeType.equals(ChangeType.DELETE))); |
| | | item.add(new BookmarkablePageLink<Void>("blame", BlamePage.class, WicketUtils |
| | | .newPathParameter(repositoryName, entry.commitId, entry.path)) |
| | |
| | | import com.gitblit.models.GitNote;
|
| | | import com.gitblit.models.PathModel.PathChangeModel;
|
| | | import com.gitblit.models.SubmoduleModel;
|
| | | import com.gitblit.servlet.RawServlet;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.wicket.CacheControl;
|
| | | import com.gitblit.wicket.CacheControl.LastModified;
|
| | |
| | | item.add(new BookmarkablePageLink<Void>("view", BlobPage.class, WicketUtils
|
| | | .newPathParameter(repositoryName, entry.commitId, entry.path))
|
| | | .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
|
| | | item.add(new BookmarkablePageLink<Void>("raw", RawPage.class, WicketUtils
|
| | | .newPathParameter(repositoryName, entry.commitId, entry.path))
|
| | | String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, entry.commitId, entry.path);
|
| | | item.add(new ExternalLink("raw", rawUrl)
|
| | | .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
|
| | | item.add(new BookmarkablePageLink<Void>("blame", BlamePage.class, WicketUtils
|
| | | .newPathParameter(repositoryName, entry.commitId, entry.path))
|
| | |
| | | import com.gitblit.models.RefModel; |
| | | import com.gitblit.models.RepositoryModel; |
| | | import com.gitblit.models.SubmoduleModel; |
| | | import com.gitblit.servlet.RawServlet; |
| | | import com.gitblit.utils.DiffUtils; |
| | | import com.gitblit.utils.DiffUtils.DiffOutput; |
| | | import com.gitblit.utils.DiffUtils.DiffOutputType; |
| | |
| | | item.add(new BookmarkablePageLink<Void>("view", BlobPage.class, WicketUtils |
| | | .newPathParameter(repositoryName, endId, entry.path)) |
| | | .setEnabled(!entry.changeType.equals(ChangeType.DELETE))); |
| | | item.add(new BookmarkablePageLink<Void>("raw", RawPage.class, WicketUtils |
| | | .newPathParameter(repositoryName, endId, entry.path)) |
| | | String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, endId, entry.path); |
| | | item.add(new ExternalLink("raw", rawUrl) |
| | | .setEnabled(!entry.changeType.equals(ChangeType.DELETE))); |
| | | item.add(new BookmarkablePageLink<Void>("blame", BlamePage.class, WicketUtils |
| | | .newPathParameter(repositoryName, endId, entry.path)) |
| | |
| | |
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.DailyLogEntry;
|
| | | import com.gitblit.models.Menu.ParameterMenuItem;
|
| | | import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
|
| | | import com.gitblit.models.Metric;
|
| | | import com.gitblit.models.NavLink;
|
| | | import com.gitblit.models.RefLogEntry;
|
| | | import com.gitblit.models.RepositoryCommit;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | |
| | | import com.gitblit.utils.RefLogUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebApp;
|
| | | import com.gitblit.wicket.PageRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
|
| | | import com.gitblit.wicket.charting.Chart;
|
| | | import com.gitblit.wicket.charting.Charts;
|
| | | import com.gitblit.wicket.charting.Flotr2Charts;
|
| | |
| | | }
|
| | |
|
| | | @Override
|
| | | protected void addDropDownMenus(List<PageRegistration> pages) {
|
| | | protected void addDropDownMenus(List<NavLink> navLinks) {
|
| | | PageParameters params = getPageParameters();
|
| | |
|
| | | DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",
|
| | | DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",
|
| | | GitBlitWebApp.get().getHomePage());
|
| | |
|
| | | // preserve repository filter option on time choices
|
| | |
| | |
|
| | | if (menu.menuItems.size() > 0) {
|
| | | // Reset Filter
|
| | | menu.menuItems.add(new DropDownMenuItem(getString("gb.reset"), null, null));
|
| | | menu.menuItems.add(new ParameterMenuItem(getString("gb.reset")));
|
| | | }
|
| | |
|
| | | pages.add(menu);
|
| | | navLinks.add(menu);
|
| | | }
|
| | |
|
| | |
|
| | |
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | |
|
| | | import com.gitblit.servlet.RawServlet;
|
| | | import com.gitblit.utils.BugtraqProcessor;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
| | | WicketUtils.newPathParameter(repositoryName, objectId, documentPath)));
|
| | | fragment.add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class,
|
| | | WicketUtils.newPathParameter(repositoryName, objectId, documentPath)));
|
| | | fragment.add(new BookmarkablePageLink<Void>("rawLink", RawPage.class, WicketUtils.newPathParameter(
|
| | | repositoryName, objectId, documentPath)));
|
| | | String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, objectId, documentPath);
|
| | | fragment.add(new ExternalLink("rawLink", rawUrl));
|
| | |
|
| | | fragment.add(new Label("content", markupDoc.html).setEscapeModelStrings(false));
|
| | | add(fragment);
|
| | |
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | |
|
| | | import com.gitblit.models.PathModel;
|
| | | import com.gitblit.servlet.RawServlet;
|
| | | import com.gitblit.utils.ByteFormat;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
| | | WicketUtils.newPathParameter(repositoryName, commitId, doc.documentPath)));
|
| | | item.add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class,
|
| | | WicketUtils.newPathParameter(repositoryName, commitId, doc.documentPath)));
|
| | | item.add(new BookmarkablePageLink<Void>("rawLink", RawPage.class, WicketUtils.newPathParameter(
|
| | | repositoryName, commitId, doc.documentPath)));
|
| | | String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, commitId, doc.documentPath);
|
| | | item.add(new ExternalLink("rawLink", rawUrl));
|
| | |
|
| | | // document content
|
| | | String file = StringUtils.getLastPathElement(doc.documentPath);
|
| | |
| | | // links
|
| | | item.add(new BookmarkablePageLink<Void>("view", DocPage.class, WicketUtils
|
| | | .newPathParameter(repositoryName, id, entry.path)));
|
| | | item.add(new BookmarkablePageLink<Void>("raw", RawPage.class, WicketUtils
|
| | | .newPathParameter(repositoryName, id, entry.path)));
|
| | | String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, id, entry.path);
|
| | | item.add(new ExternalLink("raw", rawUrl));
|
| | | item.add(new BookmarkablePageLink<Void>("blame", BlamePage.class, WicketUtils
|
| | | .newPathParameter(repositoryName, id, entry.path)));
|
| | | item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class, WicketUtils
|
New file |
| | |
| | | <!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"> |
| | |
|
| | | <wicket:extend>
|
| | | <body onload="document.getElementById('name').focus();">
|
| | | |
| | | <div class="container">
|
| | | <!-- page header -->
|
| | | <div class="title" style="font-size: 22px; color: rgb(0, 32, 96);padding: 3px 0px 7px;">
|
| | | <span class="project"><wicket:message key="gb.editMilestone"></wicket:message></span>
|
| | | </div>
|
| | |
|
| | | <form style="padding-top:5px;" wicket:id="editForm">
|
| | | <div class="row">
|
| | | <div class="span12">
|
| | | <!-- Edit Milestone Table -->
|
| | | <table class="ticket">
|
| | | <tr><th><wicket:message key="gb.milestone"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="name" id="name"></input></td></tr>
|
| | | <tr><th><wicket:message key="gb.due"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="due"></input> <span class="help-inline" wicket:id="dueFormat"></span></td></tr>
|
| | | <tr><th><wicket:message key="gb.status"></wicket:message><span style="color:red;">*</span></th><td class="edit"><select class="input-large" wicket:id="status"></select></td></tr>
|
| | | <tr><th></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="notify" /> <span class="help-inline"><wicket:message key="gb.notifyChangedOpenTickets"></wicket:message></span></label></td></tr>
|
| | | </table>
|
| | | </div>
|
| | | </div> |
| | |
|
| | | <div class="row">
|
| | | <div class="span12">
|
| | | <div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" /> <input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" /> <input class="btn btn-danger" type="submit" value="Delete" wicket:message="value:gb.delete" wicket:id="delete" /></div>
|
| | | </div>
|
| | | </div>
|
| | | </form>
|
| | | </div>
|
| | | </body>
|
| | |
|
| | | </wicket:extend>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.pages;
|
| | |
|
| | | import java.text.MessageFormat;
|
| | | import java.util.Arrays;
|
| | | import java.util.Date;
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.RestartResponseException;
|
| | | import org.apache.wicket.ajax.AjaxRequestTarget;
|
| | | import org.apache.wicket.ajax.markup.html.form.AjaxButton;
|
| | | import org.apache.wicket.extensions.markup.html.form.DateTextField;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.Button;
|
| | | import org.apache.wicket.markup.html.form.CheckBox;
|
| | | import org.apache.wicket.markup.html.form.DropDownChoice;
|
| | | import org.apache.wicket.markup.html.form.Form;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.markup.html.link.Link;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | |
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.TicketModel;
|
| | | import com.gitblit.models.TicketModel.Status;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.tickets.TicketMilestone;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation;
|
| | |
|
| | | /**
|
| | | * Page for creating a new milestone.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class EditMilestonePage extends RepositoryPage {
|
| | |
|
| | | private final String oldName;
|
| | |
|
| | | private IModel<String> nameModel;
|
| | |
|
| | | private IModel<Date> dueModel;
|
| | |
|
| | | private IModel<Status> statusModel;
|
| | |
|
| | | private IModel<Boolean> notificationModel;
|
| | |
|
| | | public EditMilestonePage(PageParameters params) {
|
| | | super(params);
|
| | |
|
| | | RepositoryModel model = getRepositoryModel();
|
| | | if (!app().tickets().isAcceptingTicketUpdates(model)) {
|
| | | // ticket service is read-only
|
| | | throw new RestartResponseException(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | }
|
| | |
|
| | | UserModel currentUser = GitBlitWebSession.get().getUser();
|
| | | if (currentUser == null) {
|
| | | currentUser = UserModel.ANONYMOUS;
|
| | | }
|
| | |
|
| | | if (!currentUser.isAuthenticated || !currentUser.canAdmin(model)) {
|
| | | // administration prohibited
|
| | | throw new RestartResponseException(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | }
|
| | |
|
| | | oldName = WicketUtils.getObject(params);
|
| | | if (StringUtils.isEmpty(oldName)) {
|
| | | // milestone not specified
|
| | | throw new RestartResponseException(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | }
|
| | |
|
| | | TicketMilestone tm = app().tickets().getMilestone(getRepositoryModel(), oldName);
|
| | | if (tm == null) {
|
| | | // milestone does not exist
|
| | | throw new RestartResponseException(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | }
|
| | |
|
| | | setStatelessHint(false);
|
| | | setOutputMarkupId(true);
|
| | |
|
| | | Form<Void> form = new Form<Void>("editForm");
|
| | | add(form);
|
| | |
|
| | | nameModel = Model.of(tm.name);
|
| | | dueModel = Model.of(tm.due);
|
| | | statusModel = Model.of(tm.status);
|
| | | notificationModel = Model.of(true);
|
| | |
|
| | | form.add(new TextField<String>("name", nameModel));
|
| | | form.add(new DateTextField("due", dueModel, "yyyy-MM-dd"));
|
| | | form.add(new Label("dueFormat", "yyyy-MM-dd"));
|
| | | form.add(new CheckBox("notify", notificationModel));
|
| | |
|
| | | List<Status> statusChoices = Arrays.asList(Status.Open, Status.Closed);
|
| | | form.add(new DropDownChoice<TicketModel.Status>("status", statusModel, statusChoices));
|
| | |
|
| | | form.add(new AjaxButton("save") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
|
| | | String name = nameModel.getObject();
|
| | | if (StringUtils.isEmpty(name)) {
|
| | | return;
|
| | | }
|
| | |
|
| | | Date due = dueModel.getObject();
|
| | | Status status = statusModel.getObject();
|
| | | boolean rename = !name.equals(oldName);
|
| | | boolean notify = notificationModel.getObject();
|
| | |
|
| | | UserModel currentUser = GitBlitWebSession.get().getUser();
|
| | | String createdBy = currentUser.username;
|
| | |
|
| | | TicketMilestone tm = app().tickets().getMilestone(getRepositoryModel(), oldName);
|
| | | tm.setName(name);
|
| | | tm.setDue(due);
|
| | | tm.status = status;
|
| | |
|
| | | boolean success = true;
|
| | | if (rename) {
|
| | | success = app().tickets().renameMilestone(getRepositoryModel(), oldName, name, createdBy, notify);
|
| | | }
|
| | |
|
| | | if (success && app().tickets().updateMilestone(getRepositoryModel(), tm, createdBy)) {
|
| | | setResponsePage(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | } else {
|
| | | // TODO error
|
| | | }
|
| | | }
|
| | | });
|
| | | Button cancel = new Button("cancel") {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void onSubmit() {
|
| | | setResponsePage(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | }
|
| | | };
|
| | | cancel.setDefaultFormProcessing(false);
|
| | | form.add(cancel);
|
| | |
|
| | | Link<Void> delete = new Link<Void>("delete") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void onClick() {
|
| | | UserModel currentUser = GitBlitWebSession.get().getUser();
|
| | | String createdBy = currentUser.username;
|
| | | boolean notify = notificationModel.getObject();
|
| | |
|
| | | if (app().tickets().deleteMilestone(getRepositoryModel(), oldName, createdBy, notify)) {
|
| | | setResponsePage(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | } else {
|
| | | error(MessageFormat.format(getString("gb.milestoneDeleteFailed"), oldName));
|
| | | }
|
| | | }
|
| | | };
|
| | |
|
| | | delete.add(new JavascriptEventConfirmation("onclick", MessageFormat.format(
|
| | | getString("gb.deleteMilestone"), oldName)));
|
| | |
|
| | | form.add(delete);
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected String getPageName() {
|
| | | return getString("gb.editMilestone");
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected Class<? extends BasePage> getRepoNavPageClass() {
|
| | | return TicketsPage.class;
|
| | | }
|
| | | }
|
| | |
| | | <form style="padding-top:5px;" wicket:id="editForm">
|
| | | <div class="row">
|
| | | <div class="span12">
|
| | | <div class="tabbable">
|
| | | <div class="tabbable tabs-left">
|
| | | <!-- tab titles -->
|
| | | <ul class="nav nav-tabs">
|
| | | <li class="active"><a href="#general" data-toggle="tab"><wicket:message key="gb.general"></wicket:message></a></li>
|
| | | <li><a href="#permissions" data-toggle="tab"><wicket:message key="gb.accessPermissions"></wicket:message></a></li>
|
| | | <li><a href="#permissions" data-toggle="tab"><wicket:message key="gb.permissions"></wicket:message></a></li>
|
| | | <li><a href="#receive" data-toggle="tab"><wicket:message key="gb.receive"></wicket:message></a></li>
|
| | | <li><a href="#tickets" data-toggle="tab"><wicket:message key="gb.tickets"></wicket:message></a></li>
|
| | | <li><a href="#federation" data-toggle="tab"><wicket:message key="gb.federation"></wicket:message></a></li>
|
| | | <li><a href="#search" data-toggle="tab"><wicket:message key="gb.search"></wicket:message></a></li>
|
| | | <li><a href="#hooks" data-toggle="tab"><wicket:message key="gb.hookScripts"></wicket:message></a></li>
|
| | | <li><a href="#gc" data-toggle="tab"><wicket:message key="gb.gc"></wicket:message></a></li>
|
| | | <li><a href="#misc" data-toggle="tab"><wicket:message key="gb.miscellaneous"></wicket:message></a></li>
|
| | | </ul>
|
| | |
|
| | | <!-- tab content -->
|
| | |
| | |
|
| | | <!-- general tab -->
|
| | | <div class="tab-pane active" id="general">
|
| | | <table class="plain">
|
| | | <tbody class="settings">
|
| | | <tr><th><wicket:message key="gb.name"></wicket:message></th><td class="edit"><input class="span4" type="text" wicket:id="name" id="name" size="40" tabindex="1" /> <span class="help-inline"><wicket:message key="gb.nameDescription"></wicket:message></span></td></tr>
|
| | | <tr><th><wicket:message key="gb.description"></wicket:message></th><td class="edit"><input class="span4" type="text" wicket:id="description" size="40" tabindex="2" /></td></tr>
|
| | | <tr><th colspan="2"><hr/></th></tr>
|
| | | <tr><th><wicket:message key="gb.origin"></wicket:message></th><td class="edit"><input class="span5" type="text" wicket:id="origin" size="80" tabindex="3" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.headRef"></wicket:message></th><td class="edit"><select class="span3" wicket:id="HEAD" tabindex="4" /> <span class="help-inline"><wicket:message key="gb.headRefDescription"></wicket:message></span></td></tr>
|
| | | <tr><th><wicket:message key="gb.gcPeriod"></wicket:message></th><td class="edit"><select class="span2" wicket:id="gcPeriod" tabindex="5" /> <span class="help-inline"><wicket:message key="gb.gcPeriodDescription"></wicket:message></span></td></tr>
|
| | | <tr><th><wicket:message key="gb.gcThreshold"></wicket:message></th><td class="edit"><input class="span1" type="text" wicket:id="gcThreshold" tabindex="6" /> <span class="help-inline"><wicket:message key="gb.gcThresholdDescription"></wicket:message></span></td></tr>
|
| | | <tr><th colspan="2"><hr/></th></tr>
|
| | | <tr><th><wicket:message key="gb.acceptNewTickets"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="acceptNewTickets" tabindex="7" /> <span class="help-inline"><wicket:message key="gb.acceptNewTicketsDescription"></wicket:message></span></label></td></tr>
|
| | | <tr><th><wicket:message key="gb.acceptNewPatchsets"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="acceptNewPatchsets" tabindex="8" /> <span class="help-inline"><wicket:message key="gb.acceptNewPatchsetsDescription"></wicket:message></span></label></td></tr>
|
| | | <tr><th><wicket:message key="gb.requireApproval"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="requireApproval" tabindex="9" /> <span class="help-inline"><wicket:message key="gb.requireApprovalDescription"></wicket:message></span></label></td></tr>
|
| | | <tr><th><wicket:message key="gb.mergeTo"></wicket:message></th><td class="edit"><select class="span2" wicket:id="mergeTo" tabindex="10" /> <span class="help-inline"><wicket:message key="gb.mergeToDescription"></wicket:message></span></td></tr>
|
| | | <tr><th colspan="2"><hr/></th></tr>
|
| | | <tr><th><wicket:message key="gb.enableIncrementalPushTags"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="useIncrementalPushTags" tabindex="11" /> <span class="help-inline"><wicket:message key="gb.useIncrementalPushTagsDescription"></wicket:message></span></label></td></tr>
|
| | | <tr><th><wicket:message key="gb.showRemoteBranches"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="showRemoteBranches" tabindex="12" /> <span class="help-inline"><wicket:message key="gb.showRemoteBranchesDescription"></wicket:message></span></label></td></tr>
|
| | | <tr><th><wicket:message key="gb.skipSizeCalculation"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="skipSizeCalculation" tabindex="13" /> <span class="help-inline"><wicket:message key="gb.skipSizeCalculationDescription"></wicket:message></span></label></td></tr>
|
| | | <tr><th><wicket:message key="gb.skipSummaryMetrics"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="skipSummaryMetrics" tabindex="14" /> <span class="help-inline"><wicket:message key="gb.skipSummaryMetricsDescription"></wicket:message></span></label></td></tr>
|
| | | <tr><th><wicket:message key="gb.maxActivityCommits"></wicket:message></th><td class="edit"><select class="span2" wicket:id="maxActivityCommits" tabindex="15" /> <span class="help-inline"><wicket:message key="gb.maxActivityCommitsDescription"></wicket:message></span></td></tr>
|
| | | <tr><th><wicket:message key="gb.metricAuthorExclusions"></wicket:message></th><td class="edit"><input class="span8" type="text" wicket:id="metricAuthorExclusions" size="40" tabindex="16" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.commitMessageRenderer"></wicket:message></th><td class="edit"><select class="span2" wicket:id="commitMessageRenderer" tabindex="17" /></td></tr>
|
| | | <tr><th colspan="2"><hr/></th></tr>
|
| | | <tr><th><wicket:message key="gb.mailingLists"></wicket:message></th><td class="edit"><input class="span8" type="text" wicket:id="mailingLists" size="40" tabindex="18" /></td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | |
|
| | | <div wicket:id="namePanel"></div>
|
| | | |
| | | <hr/>
|
| | | |
| | | <div wicket:id="accessPolicyPanel"></div>
|
| | | |
| | | </div>
|
| | |
|
| | | <!-- access permissions -->
|
| | | <div class="tab-pane" id="permissions">
|
| | | <table class="plain">
|
| | | <tbody class="settings">
|
| | | <tr><th><wicket:message key="gb.owners"></wicket:message></th><td class="edit"><span wicket:id="owners" tabindex="19" /> </td></tr>
|
| | | <tr><th colspan="2"><hr/></th></tr>
|
| | | <tr><th><wicket:message key="gb.accessRestriction"></wicket:message></th><td class="edit"><select class="span4" wicket:id="accessRestriction" tabindex="20" /></td></tr>
|
| | | <tr><th colspan="2"><hr/></th></tr>
|
| | | <tr><th><wicket:message key="gb.authorizationControl"></wicket:message></th><td style="padding:2px;"><span class="authorizationControl" wicket:id="authorizationControl"></span></td></tr>
|
| | | <tr><th colspan="2"><hr/></th></tr>
|
| | | <tr><th><wicket:message key="gb.isFrozen"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="isFrozen" tabindex="21" /> <span class="help-inline"><wicket:message key="gb.isFrozenDescription"></wicket:message></span></label></td></tr>
|
| | | <tr><th><wicket:message key="gb.allowForks"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="allowForks" tabindex="22" /> <span class="help-inline"><wicket:message key="gb.allowForksDescription"></wicket:message></span></label></td></tr>
|
| | | <tr><th><wicket:message key="gb.verifyCommitter"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="verifyCommitter" tabindex="23" /> <span class="help-inline"><wicket:message key="gb.verifyCommitterDescription"></wicket:message></span><br/><span class="help-inline" style="padding-left:10px;"><wicket:message key="gb.verifyCommitterNote"></wicket:message></span></label></td></tr>
|
| | | <tr><th colspan="2"><hr/></th></tr>
|
| | | <tr><th><wicket:message key="gb.userPermissions"></wicket:message></th><td style="padding:2px;"><span wicket:id="users"></span></td></tr>
|
| | | <tr><th colspan="2"><hr/></th></tr>
|
| | | <tr><th><wicket:message key="gb.teamPermissions"></wicket:message></th><td style="padding:2px;"><span wicket:id="teams"></span></td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | | |
| | | <h4><wicket:message key="gb.owners"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.ownersDescription"></wicket:message></p>
|
| | | <div wicket:id="owners"></div>
|
| | | |
| | | <hr />
|
| | |
|
| | | <h4><wicket:message key="gb.userPermissions"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.userPermissionsDescription"></wicket:message></p>
|
| | | <div wicket:id="users"></div>
|
| | | |
| | | <hr />
|
| | |
|
| | | <h4><wicket:message key="gb.teamPermissions"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.teamPermissionsDescription"></wicket:message></p>
|
| | | <div wicket:id="teams"></div>
|
| | | |
| | | </div>
|
| | |
|
| | | <!-- federation -->
|
| | | <div class="tab-pane" id="federation">
|
| | | <!-- receive -->
|
| | | <div class="tab-pane" id="receive">
|
| | | <h4><wicket:message key="gb.receiveSettings"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.receiveSettingsDescription"></wicket:message></p>
|
| | | |
| | | <hr/>
|
| | | |
| | | <div wicket:id="isFrozen"></div>
|
| | | <div wicket:id="verifyCommitter"></div>
|
| | | <div wicket:id="incrementalPushTags"></div>
|
| | | |
| | | <hr />
|
| | | |
| | | <h4><wicket:message key="gb.preReceiveScripts"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.preReceiveDescription"></wicket:message></p>
|
| | | |
| | | <table class="plain">
|
| | | <tbody class="settings">
|
| | | <tr><th><wicket:message key="gb.federationStrategy"></wicket:message></th><td class="edit"><select class="span4" wicket:id="federationStrategy" tabindex="24" /></td></tr>
|
| | | <tr><th><wicket:message key="gb.federationSets"></wicket:message></th><td style="padding:2px;"><span wicket:id="federationSets"></span></td></tr>
|
| | | <tr>
|
| | | <td style="padding:2px;"><span wicket:id="preReceiveScripts"></span></td>
|
| | | <td style="vertical-align: top;"><span wicket:id="inheritedPreReceive"></span></td>
|
| | | </tr>
|
| | | </tbody>
|
| | | </table>
|
| | |
|
| | | <hr />
|
| | | |
| | | <h4><wicket:message key="gb.postReceiveScripts"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.postReceiveDescription"></wicket:message></p>
|
| | | |
| | | <table class="plain">
|
| | | <tbody class="settings">
|
| | | <tr>
|
| | | <td style="padding:2px;"><span wicket:id="postReceiveScripts"></span></td>
|
| | | <td style="vertical-align: top;"><span wicket:id="inheritedPostReceive"></span></td>
|
| | | </tr>
|
| | | </tbody>
|
| | | </table>
|
| | |
|
| | | <div wicket:id="customFieldsSection">
|
| | | <hr />
|
| | | |
| | | <h4><wicket:message key="gb.customFields"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.customFieldsDescription"></wicket:message></p>
|
| | | <table class="plain">
|
| | | <tbody class="settings">
|
| | | <tr wicket:id="customFieldsListView"><th><span wicket:id="customFieldLabel"></span></th><td class="edit"><input class="span8" type="text" wicket:id="customFieldValue" /></td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | | </div>
|
| | | |
| | | </div>
|
| | |
|
| | | <!-- tickets tab --> |
| | | <div class="tab-pane" id="tickets">
|
| | |
|
| | | <h4><wicket:message key="gb.ticketSettings"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.ticketsWelcome"></wicket:message></p>
|
| | | |
| | | <hr/>
|
| | | |
| | | <div wicket:id="acceptNewPatchsets"></div>
|
| | | <div wicket:id="acceptNewTickets"></div>
|
| | | <div wicket:id="requireApproval"></div>
|
| | | <div wicket:id="mergeTo"></div>
|
| | | |
| | | </div>
|
| | | |
| | | <!-- federation -->
|
| | | <div class="tab-pane" id="federation">
|
| | | <h4><wicket:message key="gb.federation"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.federationRepositoryDescription"></wicket:message></p>
|
| | | |
| | | <hr/>
|
| | | |
| | | <div wicket:id="federationStrategy"></div>
|
| | |
|
| | | <hr />
|
| | | |
| | | <h4><wicket:message key="gb.federationSets"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.federationSetsDescription"></wicket:message></p>
|
| | |
|
| | | <div wicket:id="federationSets"></div>
|
| | | </div>
|
| | |
|
| | | <!-- search -->
|
| | | <div class="tab-pane" id="search">
|
| | | <table class="plain">
|
| | | <tbody class="settings">
|
| | | <tr><th><wicket:message key="gb.indexedBranches"></wicket:message></th><td style="padding:2px;"><span wicket:id="indexedBranches"></span></td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | | |
| | | <h4><wicket:message key="gb.indexedBranches"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.indexedBranchesDescription"></wicket:message></p>
|
| | | |
| | | <div wicket:id="indexedBranches"></div>
|
| | | </div>
|
| | |
|
| | | <!-- hooks -->
|
| | | <div class="tab-pane" id="hooks">
|
| | | <table class="plain">
|
| | | <tbody class="settings">
|
| | | <tr><th><wicket:message key="gb.preReceiveScripts"></wicket:message><p></p><span wicket:id="inheritedPreReceive"></span></th><td style="padding:2px;"><span wicket:id="preReceiveScripts"></span></td></tr>
|
| | | <tr><th><wicket:message key="gb.postReceiveScripts"></wicket:message><p></p><span wicket:id="inheritedPostReceive"></span></th><td style="padding:2px;"><span wicket:id="postReceiveScripts"></span></td></tr>
|
| | | <div wicket:id="customFieldsSection">
|
| | | <tr><td colspan="2"><h3><wicket:message key="gb.customFields"></wicket:message> <small><wicket:message key="gb.customFieldsDescription"></wicket:message></small></h3></td></tr>
|
| | | <tr wicket:id="customFieldsListView"><th><span wicket:id="customFieldLabel"></span></th><td class="edit"><input class="span8" type="text" wicket:id="customFieldValue" /></td></tr>
|
| | | </div>
|
| | | </tbody>
|
| | | </table>
|
| | | <!-- garbage collection -->
|
| | | <div class="tab-pane" id="gc">
|
| | |
|
| | | <h4><wicket:message key="gb.garbageCollection"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.garbageCollectionDescription"></wicket:message></p>
|
| | | |
| | | <div wicket:id="gcPeriod"></div>
|
| | | <div wicket:id="gcThreshold"></div>
|
| | | </div>
|
| | | |
| | | <!-- misc -->
|
| | | <div class="tab-pane" id="misc">
|
| | |
|
| | | <div wicket:id="origin"></div>
|
| | | <div wicket:id="head"></div>
|
| | |
|
| | | <hr/>
|
| | | |
| | | <div wicket:id="showRemoteBranches"></div>
|
| | | <div wicket:id="skipSizeCalculation"></div>
|
| | | <div wicket:id="skipSummaryMetrics"></div>
|
| | | <div wicket:id="maxActivityCommits"></div>
|
| | | <div wicket:id="commitMessageRenderer"></div>
|
| | | <div wicket:id="metricAuthorExclusions"></div>
|
| | | <div wicket:id="mailingLists"></div>
|
| | | |
| | | </div>
|
| | | |
| | | <div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" /> <input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" /> <input class="btn btn-danger" type="submit" value="Delete" wicket:message="value:gb.delete" wicket:id="delete" /></div>
|
| | | |
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | |
|
| | | <div class="row">
|
| | | <div class="span12">
|
| | | <div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" /> <input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" /></div>
|
| | | </div>
|
| | | </div>
|
| | |
|
| | | </form>
|
| | | </body>
|
| | |
|
| | | </wicket:extend>
|
| | | </html> |
| | |
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.ajax.AjaxRequestTarget;
|
| | | import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
|
| | | import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
|
| | | import org.apache.wicket.behavior.SimpleAttributeModifier;
|
| | | import org.apache.wicket.extensions.markup.html.form.palette.Palette;
|
| | | import org.apache.wicket.markup.html.WebMarkupContainer;
|
| | |
| | | import org.apache.wicket.markup.html.form.DropDownChoice;
|
| | | import org.apache.wicket.markup.html.form.Form;
|
| | | import org.apache.wicket.markup.html.form.IChoiceRenderer;
|
| | | import org.apache.wicket.markup.html.form.RadioChoice;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.markup.html.link.Link;
|
| | | import org.apache.wicket.markup.html.list.ListItem;
|
| | | import org.apache.wicket.markup.html.list.ListView;
|
| | | import org.apache.wicket.model.CompoundPropertyModel;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | | import org.apache.wicket.model.PropertyModel;
|
| | | import org.apache.wicket.model.util.CollectionModel;
|
| | | import org.apache.wicket.model.util.ListModel;
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | |
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.StringChoiceRenderer;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.AccessPolicyPanel;
|
| | | import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation;
|
| | | import com.gitblit.wicket.panels.BooleanOption;
|
| | | import com.gitblit.wicket.panels.BulletListPanel;
|
| | | import com.gitblit.wicket.panels.ChoiceOption;
|
| | | import com.gitblit.wicket.panels.RegistrantPermissionsPanel;
|
| | | import com.gitblit.wicket.panels.RepositoryNamePanel;
|
| | | import com.gitblit.wicket.panels.TextOption;
|
| | |
|
| | | public class EditRepositoryPage extends RootSubPage {
|
| | |
|
| | | private final boolean isCreate;
|
| | |
|
| | | RepositoryNamePanel namePanel;
|
| | |
|
| | | AccessPolicyPanel accessPolicyPanel;
|
| | |
|
| | | private boolean isAdmin;
|
| | |
|
| | |
| | | }
|
| | | }
|
| | | final Palette<UserChoice> ownersPalette = new Palette<UserChoice>("owners", new ListModel<UserChoice>(owners), new CollectionModel<UserChoice>(
|
| | | persons), new ChoiceRenderer<UserChoice>(null, "userId"), 12, true);
|
| | | persons), new ChoiceRenderer<UserChoice>(null, "userId"), 12, false);
|
| | |
|
| | | // indexed local branches palette
|
| | | List<String> allLocalBranches = new ArrayList<String>();
|
| | |
| | | @Override
|
| | | protected void onSubmit() {
|
| | | try {
|
| | | // confirm a repository name was entered
|
| | | if (repositoryModel.name == null && StringUtils.isEmpty(repositoryModel.name)) {
|
| | | error(getString("gb.pleaseSetRepositoryName"));
|
| | | if (!namePanel.updateModel(repositoryModel)) {
|
| | | return;
|
| | | }
|
| | |
|
| | | // ensure name is trimmed
|
| | | repositoryModel.name = repositoryModel.name.trim();
|
| | |
|
| | | // automatically convert backslashes to forward slashes
|
| | | repositoryModel.name = repositoryModel.name.replace('\\', '/');
|
| | | // Automatically replace // with /
|
| | | repositoryModel.name = repositoryModel.name.replace("//", "/");
|
| | |
|
| | | // prohibit folder paths
|
| | | if (repositoryModel.name.startsWith("/")) {
|
| | | error(getString("gb.illegalLeadingSlash"));
|
| | | return;
|
| | | }
|
| | | if (repositoryModel.name.startsWith("../")) {
|
| | | error(getString("gb.illegalRelativeSlash"));
|
| | | return;
|
| | | }
|
| | | if (repositoryModel.name.contains("/../")) {
|
| | | error(getString("gb.illegalRelativeSlash"));
|
| | | return;
|
| | | }
|
| | | if (repositoryModel.name.endsWith("/")) {
|
| | | repositoryModel.name = repositoryModel.name.substring(0, repositoryModel.name.length() - 1);
|
| | | }
|
| | |
|
| | | // confirm valid characters in repository name
|
| | | Character c = StringUtils.findInvalidCharacter(repositoryModel.name);
|
| | | if (c != null) {
|
| | | error(MessageFormat.format(getString("gb.illegalCharacterRepositoryName"),
|
| | | c));
|
| | | return;
|
| | | }
|
| | |
|
| | | if (user.canCreate() && !user.canAdmin() && allowEditName) {
|
| | | // ensure repository name begins with the user's path
|
| | | if (!repositoryModel.name.startsWith(user.getPersonalPath())) {
|
| | | error(MessageFormat.format(getString("gb.illegalPersonalRepositoryLocation"),
|
| | | user.getPersonalPath()));
|
| | | return;
|
| | | }
|
| | |
|
| | | if (repositoryModel.name.equals(user.getPersonalPath())) {
|
| | | // reset path prefix and show error
|
| | | repositoryModel.name = user.getPersonalPath() + "/";
|
| | | error(getString("gb.pleaseSetRepositoryName"));
|
| | | return;
|
| | | }
|
| | | }
|
| | |
|
| | | // confirm access restriction selection
|
| | |
| | | return;
|
| | | }
|
| | | setRedirect(false);
|
| | | if (isCreate) {
|
| | | setResponsePage(RepositoriesPage.class);
|
| | | } else {
|
| | | setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name));
|
| | | }
|
| | | setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name));
|
| | | }
|
| | | };
|
| | |
|
| | | // do not let the browser pre-populate these fields
|
| | | form.add(new SimpleAttributeModifier("autocomplete", "off"));
|
| | |
|
| | | // field names reflective match RepositoryModel fields
|
| | | form.add(new TextField<String>("name").setEnabled(allowEditName));
|
| | | form.add(new TextField<String>("description"));
|
| | | form.add(ownersPalette);
|
| | | form.add(new CheckBox("allowForks").setEnabled(app().settings().getBoolean(Keys.web.allowForking, true)));
|
| | | DropDownChoice<AccessRestrictionType> accessRestriction = new DropDownChoice<AccessRestrictionType>("accessRestriction",
|
| | | AccessRestrictionType.choices(app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)), new AccessRestrictionRenderer());
|
| | | form.add(accessRestriction);
|
| | | form.add(new CheckBox("isFrozen"));
|
| | | // TODO enable origin definition
|
| | | form.add(new TextField<String>("origin").setEnabled(false/* isCreate */));
|
| | |
|
| | | // allow relinking HEAD to a branch or tag other than master on edit repository
|
| | | // Determine available refs & branches
|
| | | List<String> availableRefs = new ArrayList<String>();
|
| | | List<String> availableBranches = new ArrayList<String>();
|
| | | if (!ArrayUtils.isEmpty(repositoryModel.availableRefs)) {
|
| | |
| | | }
|
| | | }
|
| | | }
|
| | | form.add(new DropDownChoice<String>("HEAD", availableRefs).setEnabled(availableRefs.size() > 0));
|
| | |
|
| | | boolean gcEnabled = app().settings().getBoolean(Keys.git.enableGarbageCollection, false);
|
| | | int defaultGcPeriod = app().settings().getInteger(Keys.git.defaultGarbageCollectionPeriod, 7);
|
| | | if (repositoryModel.gcPeriod == 0) {
|
| | | repositoryModel.gcPeriod = defaultGcPeriod;
|
| | | }
|
| | | List<Integer> gcPeriods = Arrays.asList(1, 2, 3, 4, 5, 7, 10, 14 );
|
| | | form.add(new DropDownChoice<Integer>("gcPeriod", gcPeriods, new GCPeriodRenderer()).setEnabled(gcEnabled));
|
| | | form.add(new TextField<String>("gcThreshold").setEnabled(gcEnabled));
|
| | | // do not let the browser pre-populate these fields
|
| | | form.add(new SimpleAttributeModifier("autocomplete", "off"));
|
| | |
|
| | | // federation strategies - remove ORIGIN choice if this repository has
|
| | | // no origin.
|
| | | List<FederationStrategy> federationStrategies = new ArrayList<FederationStrategy>(
|
| | | Arrays.asList(FederationStrategy.values()));
|
| | | if (StringUtils.isEmpty(repositoryModel.origin)) {
|
| | | federationStrategies.remove(FederationStrategy.FEDERATE_ORIGIN);
|
| | | }
|
| | | form.add(new DropDownChoice<FederationStrategy>("federationStrategy", federationStrategies,
|
| | | new FederationTypeRenderer()));
|
| | | form.add(new CheckBox("acceptNewPatchsets"));
|
| | | form.add(new CheckBox("acceptNewTickets")); |
| | | form.add(new CheckBox("requireApproval"));
|
| | | form.add(new DropDownChoice<String>("mergeTo", availableBranches).setEnabled(availableBranches.size() > 0));
|
| | | form.add(new CheckBox("useIncrementalPushTags"));
|
| | | form.add(new CheckBox("showRemoteBranches"));
|
| | | form.add(new CheckBox("skipSizeCalculation"));
|
| | | form.add(new CheckBox("skipSummaryMetrics"));
|
| | | List<Integer> maxActivityCommits = Arrays.asList(-1, 0, 25, 50, 75, 100, 150, 200, 250, 500);
|
| | | form.add(new DropDownChoice<Integer>("maxActivityCommits", maxActivityCommits, new MaxActivityCommitsRenderer()));
|
| | |
|
| | | metricAuthorExclusions = new Model<String>(ArrayUtils.isEmpty(repositoryModel.metricAuthorExclusions) ? ""
|
| | | : StringUtils.flattenStrings(repositoryModel.metricAuthorExclusions, " "));
|
| | | form.add(new TextField<String>("metricAuthorExclusions", metricAuthorExclusions));
|
| | | //
|
| | | //
|
| | | // GENERAL
|
| | | //
|
| | | namePanel = new RepositoryNamePanel("namePanel", repositoryModel);
|
| | | namePanel.setEditable(allowEditName);
|
| | | form.add(namePanel);
|
| | |
|
| | | mailingLists = new Model<String>(ArrayUtils.isEmpty(repositoryModel.mailingLists) ? ""
|
| | | : StringUtils.flattenStrings(repositoryModel.mailingLists, " "));
|
| | | form.add(new TextField<String>("mailingLists", mailingLists));
|
| | | form.add(indexedBranchesPalette);
|
| | | // XXX AccessPolicyPanel is defined later.
|
| | |
|
| | | List<AuthorizationControl> acList = Arrays.asList(AuthorizationControl.values());
|
| | | final RadioChoice<AuthorizationControl> authorizationControl = new RadioChoice<Constants.AuthorizationControl>(
|
| | | "authorizationControl", acList, new AuthorizationControlRenderer());
|
| | | form.add(authorizationControl);
|
| | | form.add(new ChoiceOption<String>("head",
|
| | | getString("gb.headRef"),
|
| | | getString("gb.headRefDescription"),
|
| | | new PropertyModel<String>(repositoryModel, "HEAD"),
|
| | | availableRefs));
|
| | |
|
| | | final CheckBox verifyCommitter = new CheckBox("verifyCommitter");
|
| | | verifyCommitter.setOutputMarkupId(true);
|
| | | form.add(verifyCommitter);
|
| | |
|
| | | //
|
| | | // PERMISSIONS
|
| | | //
|
| | | form.add(ownersPalette);
|
| | | form.add(usersPalette);
|
| | | form.add(teamsPalette);
|
| | | form.add(federationSetsPalette);
|
| | |
|
| | | //
|
| | | // TICKETS
|
| | | //
|
| | | form.add(new BooleanOption("acceptNewPatchsets",
|
| | | getString("gb.acceptNewPatchsets"),
|
| | | getString("gb.acceptNewPatchsetsDescription"),
|
| | | new PropertyModel<Boolean>(repositoryModel, "acceptNewPatchsets")));
|
| | |
|
| | | form.add(new BooleanOption("acceptNewTickets",
|
| | | getString("gb.acceptNewTickets"),
|
| | | getString("gb.acceptNewTicketsDescription"),
|
| | | new PropertyModel<Boolean>(repositoryModel, "acceptNewPatchsets")));
|
| | |
|
| | | form.add(new BooleanOption("requireApproval",
|
| | | getString("gb.requireApproval"),
|
| | | getString("gb.requireApprovalDescription"),
|
| | | new PropertyModel<Boolean>(repositoryModel, "requireApproval")));
|
| | |
|
| | | form.add(new ChoiceOption<String>("mergeTo",
|
| | | getString("gb.mergeTo"),
|
| | | getString("gb.mergeToDescription"),
|
| | | new PropertyModel<String>(repositoryModel, "mergeTo"),
|
| | | availableBranches));
|
| | |
|
| | | //
|
| | | // RECEIVE
|
| | | //
|
| | | form.add(new BooleanOption("isFrozen",
|
| | | getString("gb.isFrozen"),
|
| | | getString("gb.isFrozenDescription"),
|
| | | new PropertyModel<Boolean>(repositoryModel, "isFrozen")));
|
| | |
|
| | | form.add(new BooleanOption("incrementalPushTags",
|
| | | getString("gb.enableIncrementalPushTags"),
|
| | | getString("gb.useIncrementalPushTagsDescription"),
|
| | | new PropertyModel<Boolean>(repositoryModel, "useIncrementalPushTags")));
|
| | |
|
| | | final CheckBox verifyCommitter = new CheckBox("checkbox", new PropertyModel<Boolean>(repositoryModel, "verifyCommitter"));
|
| | | verifyCommitter.setOutputMarkupId(true);
|
| | | form.add(new BooleanOption("verifyCommitter",
|
| | | getString("gb.verifyCommitter"),
|
| | | getString("gb.verifyCommitterDescription") + "<br/>" + getString("gb.verifyCommitterNote"),
|
| | | verifyCommitter).setIsHtmlDescription(true));
|
| | |
|
| | | form.add(preReceivePalette);
|
| | | form.add(new BulletListPanel("inheritedPreReceive", getString("gb.inherited"), app().repositories()
|
| | | .getPreReceiveScriptsInherited(repositoryModel)));
|
| | |
| | | customFieldsSection.add(customFieldsListView);
|
| | | form.add(customFieldsSection.setVisible(!app().settings().getString(Keys.groovy.customFields, "").isEmpty()));
|
| | |
|
| | | //
|
| | | // FEDERATION
|
| | | //
|
| | | List<FederationStrategy> federationStrategies = new ArrayList<FederationStrategy>(
|
| | | Arrays.asList(FederationStrategy.values()));
|
| | | // federation strategies - remove ORIGIN choice if this repository has no origin.
|
| | | if (StringUtils.isEmpty(repositoryModel.origin)) {
|
| | | federationStrategies.remove(FederationStrategy.FEDERATE_ORIGIN);
|
| | | }
|
| | |
|
| | | form.add(new ChoiceOption<FederationStrategy>("federationStrategy",
|
| | | getString("gb.federationStrategy"),
|
| | | getString("gb.federationStrategyDescription"),
|
| | | new DropDownChoice<FederationStrategy>(
|
| | | "choice",
|
| | | new PropertyModel<FederationStrategy>(repositoryModel, "federationStrategy"),
|
| | | federationStrategies,
|
| | | new FederationTypeRenderer())));
|
| | |
|
| | | form.add(federationSetsPalette);
|
| | |
|
| | | //
|
| | | // SEARCH
|
| | | //
|
| | | form.add(indexedBranchesPalette);
|
| | |
|
| | | //
|
| | | // GARBAGE COLLECTION
|
| | | //
|
| | | boolean gcEnabled = app().settings().getBoolean(Keys.git.enableGarbageCollection, false);
|
| | | int defaultGcPeriod = app().settings().getInteger(Keys.git.defaultGarbageCollectionPeriod, 7);
|
| | | if (repositoryModel.gcPeriod == 0) {
|
| | | repositoryModel.gcPeriod = defaultGcPeriod;
|
| | | }
|
| | | List<Integer> gcPeriods = Arrays.asList(1, 2, 3, 4, 5, 7, 10, 14 );
|
| | | form.add(new ChoiceOption<Integer>("gcPeriod",
|
| | | getString("gb.gcPeriod"),
|
| | | getString("gb.gcPeriodDescription"),
|
| | | new DropDownChoice<Integer>("choice",
|
| | | new PropertyModel<Integer>(repositoryModel, "gcPeriod"),
|
| | | gcPeriods,
|
| | | new GCPeriodRenderer())).setEnabled(gcEnabled));
|
| | |
|
| | | form.add(new TextOption("gcThreshold",
|
| | | getString("gb.gcThreshold"),
|
| | | getString("gb.gcThresholdDescription"),
|
| | | "span1",
|
| | | new PropertyModel<String>(repositoryModel, "gcThreshold")).setEnabled(gcEnabled));
|
| | |
|
| | | //
|
| | | // MISCELLANEOUS
|
| | | //
|
| | |
|
| | | form.add(new TextOption("origin",
|
| | | getString("gb.origin"),
|
| | | getString("gb.originDescription"),
|
| | | "span6",
|
| | | new PropertyModel<String>(repositoryModel, "origin")).setEnabled(false));
|
| | |
|
| | | form.add(new BooleanOption("showRemoteBranches",
|
| | | getString("gb.showRemoteBranches"),
|
| | | getString("gb.showRemoteBranchesDescription"),
|
| | | new PropertyModel<Boolean>(repositoryModel, "showRemoteBranches")));
|
| | |
|
| | | form.add(new BooleanOption("skipSizeCalculation",
|
| | | getString("gb.skipSizeCalculation"),
|
| | | getString("gb.skipSizeCalculationDescription"),
|
| | | new PropertyModel<Boolean>(repositoryModel, "skipSizeCalculation")));
|
| | |
|
| | | form.add(new BooleanOption("skipSummaryMetrics",
|
| | | getString("gb.skipSummaryMetrics"),
|
| | | getString("gb.skipSummaryMetricsDescription"),
|
| | | new PropertyModel<Boolean>(repositoryModel, "skipSummaryMetrics")));
|
| | |
|
| | | List<Integer> maxActivityCommits = Arrays.asList(-1, 0, 25, 50, 75, 100, 150, 200, 250, 500);
|
| | | form.add(new ChoiceOption<Integer>("maxActivityCommits",
|
| | | getString("gb.maxActivityCommits"),
|
| | | getString("gb.maxActivityCommitsDescription"),
|
| | | new DropDownChoice<Integer>("choice",
|
| | | new PropertyModel<Integer>(repositoryModel, "maxActivityCommits"),
|
| | | maxActivityCommits,
|
| | | new MaxActivityCommitsRenderer())));
|
| | |
|
| | | List<CommitMessageRenderer> renderers = Arrays.asList(CommitMessageRenderer.values());
|
| | | form.add(new ChoiceOption<CommitMessageRenderer>("commitMessageRenderer",
|
| | | getString("gb.commitMessageRenderer"),
|
| | | getString("gb.commitMessageRendererDescription"),
|
| | | new DropDownChoice<CommitMessageRenderer>("choice",
|
| | | new PropertyModel<CommitMessageRenderer>(repositoryModel, "commitMessageRenderer"),
|
| | | renderers)));
|
| | |
|
| | | metricAuthorExclusions = new Model<String>(ArrayUtils.isEmpty(repositoryModel.metricAuthorExclusions) ? ""
|
| | | : StringUtils.flattenStrings(repositoryModel.metricAuthorExclusions, " "));
|
| | |
|
| | | form.add(new TextOption("metricAuthorExclusions",
|
| | | getString("gb.metricAuthorExclusions"),
|
| | | getString("gb.metricAuthorExclusions"),
|
| | | "span6",
|
| | | metricAuthorExclusions));
|
| | |
|
| | | mailingLists = new Model<String>(ArrayUtils.isEmpty(repositoryModel.mailingLists) ? ""
|
| | | : StringUtils.flattenStrings(repositoryModel.mailingLists, " "));
|
| | |
|
| | | form.add(new TextOption("mailingLists",
|
| | | getString("gb.mailingLists"),
|
| | | getString("gb.mailingLists"),
|
| | | "span6",
|
| | | mailingLists));
|
| | |
|
| | |
|
| | | // initial enable/disable of permission controls
|
| | | if (repositoryModel.accessRestriction.equals(AccessRestrictionType.NONE)) {
|
| | | // anonymous everything, disable all controls
|
| | | usersPalette.setEnabled(false);
|
| | | teamsPalette.setEnabled(false);
|
| | | authorizationControl.setEnabled(false);
|
| | | verifyCommitter.setEnabled(false);
|
| | | } else {
|
| | | // authenticated something
|
| | | // enable authorization controls
|
| | | authorizationControl.setEnabled(true);
|
| | | verifyCommitter.setEnabled(true);
|
| | |
|
| | | boolean allowFineGrainedControls = repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED);
|
| | |
| | | teamsPalette.setEnabled(allowFineGrainedControls);
|
| | | }
|
| | |
|
| | | accessRestriction.add(new AjaxFormComponentUpdatingBehavior("onchange") {
|
| | | //
|
| | | // ACCESS POLICY PANEL (GENERAL)
|
| | | //
|
| | | AjaxFormChoiceComponentUpdatingBehavior callback = new AjaxFormChoiceComponentUpdatingBehavior() {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | protected void onUpdate(AjaxRequestTarget target) {
|
| | | // enable/disable permissions panel based on access restriction
|
| | | accessPolicyPanel.updateModel(repositoryModel);
|
| | |
|
| | | boolean allowAuthorizationControl = repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE);
|
| | | authorizationControl.setEnabled(allowAuthorizationControl);
|
| | | verifyCommitter.setEnabled(allowAuthorizationControl);
|
| | |
|
| | | boolean allowFineGrainedControls = allowAuthorizationControl && repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED);
|
| | |
| | | repositoryModel.authorizationControl = AuthorizationControl.NAMED;
|
| | | }
|
| | |
|
| | | target.addComponent(authorizationControl);
|
| | | target.addComponent(verifyCommitter);
|
| | | target.addComponent(usersPalette);
|
| | | target.addComponent(teamsPalette);
|
| | | }
|
| | | });
|
| | | };
|
| | |
|
| | | authorizationControl.add(new AjaxFormChoiceComponentUpdatingBehavior() {
|
| | | accessPolicyPanel = new AccessPolicyPanel("accessPolicyPanel", repositoryModel, callback);
|
| | | form.add(accessPolicyPanel);
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | protected void onUpdate(AjaxRequestTarget target) {
|
| | | // enable/disable permissions panel based on access restriction
|
| | | boolean allowAuthorizationControl = repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE);
|
| | | authorizationControl.setEnabled(allowAuthorizationControl);
|
| | |
|
| | | boolean allowFineGrainedControls = allowAuthorizationControl && repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED);
|
| | | usersPalette.setEnabled(allowFineGrainedControls);
|
| | | teamsPalette.setEnabled(allowFineGrainedControls);
|
| | |
|
| | | if (allowFineGrainedControls) {
|
| | | repositoryModel.authorizationControl = AuthorizationControl.NAMED;
|
| | | }
|
| | |
|
| | | target.addComponent(authorizationControl);
|
| | | target.addComponent(usersPalette);
|
| | | target.addComponent(teamsPalette);
|
| | | }
|
| | | });
|
| | |
|
| | | List<CommitMessageRenderer> renderers = Arrays.asList(CommitMessageRenderer.values());
|
| | | DropDownChoice<CommitMessageRenderer> messageRendererChoice = new DropDownChoice<CommitMessageRenderer>("commitMessageRenderer", renderers);
|
| | | form.add(messageRendererChoice);
|
| | |
|
| | | //
|
| | | // FORM CONTROLS
|
| | | //
|
| | | form.add(new Button("save"));
|
| | | Button cancel = new Button("cancel") {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
| | | };
|
| | | cancel.setDefaultFormProcessing(false);
|
| | | form.add(cancel);
|
| | |
|
| | | // the user can delete if deletions are allowed AND the user is an admin or the personal owner
|
| | | // assigned ownership is not sufficient to allow deletion
|
| | | boolean canDelete = !isCreate && app().repositories().canDelete(repositoryModel)
|
| | | && (user.canAdmin() || user.isMyPersonalRepository(repositoryModel.name));
|
| | |
|
| | | Link<Void> delete = new Link<Void>("delete") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void onClick() {
|
| | | RepositoryModel latestModel = app().repositories().getRepositoryModel(repositoryModel.name);
|
| | | boolean canDelete = app().repositories().canDelete(latestModel);
|
| | | if (canDelete) {
|
| | | if (app().repositories().deleteRepositoryModel(latestModel)) {
|
| | | info(MessageFormat.format(getString("gb.repositoryDeleted"), latestModel));
|
| | | if (latestModel.isPersonalRepository()) {
|
| | | // redirect to user's profile page
|
| | | String prefix = app().settings().getString(Keys.git.userRepositoryPrefix, "~");
|
| | | String username = latestModel.projectPath.substring(prefix.length());
|
| | | setResponsePage(UserPage.class, WicketUtils.newUsernameParameter(username));
|
| | | } else {
|
| | | // redirect to server repositories page
|
| | | setResponsePage(RepositoriesPage.class);
|
| | | }
|
| | | } else {
|
| | | error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), latestModel));
|
| | | }
|
| | | } else {
|
| | | error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), latestModel));
|
| | | }
|
| | | }
|
| | | };
|
| | |
|
| | | if (canDelete) {
|
| | | delete.add(new JavascriptEventConfirmation("onclick", MessageFormat.format(
|
| | | getString("gb.deleteRepository"), repositoryModel)));
|
| | | }
|
| | | form.add(delete.setVisible(canDelete));
|
| | |
|
| | | add(form);
|
| | | }
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | private class AccessRestrictionRenderer implements IChoiceRenderer<AccessRestrictionType> {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | private final Map<AccessRestrictionType, String> map;
|
| | |
|
| | | public AccessRestrictionRenderer() {
|
| | | map = getAccessRestrictions();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getDisplayValue(AccessRestrictionType type) {
|
| | | return map.get(type);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getIdValue(AccessRestrictionType type, int index) {
|
| | | return Integer.toString(index);
|
| | | }
|
| | | }
|
| | |
|
| | | private class FederationTypeRenderer implements IChoiceRenderer<FederationStrategy> {
|
| | |
|
| | |
| | |
|
| | | @Override
|
| | | public String getIdValue(FederationStrategy type, int index) {
|
| | | return Integer.toString(index);
|
| | | }
|
| | | }
|
| | |
|
| | | private class AuthorizationControlRenderer implements IChoiceRenderer<AuthorizationControl> {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | private final Map<AuthorizationControl, String> map;
|
| | |
|
| | | public AuthorizationControlRenderer() {
|
| | | map = getAuthorizationControls();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getDisplayValue(AuthorizationControl type) {
|
| | | return map.get(type);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String getIdValue(AuthorizationControl type, int index) {
|
| | | return Integer.toString(index);
|
| | | }
|
| | | }
|
| | |
| | |
|
| | | @Override
|
| | | protected Class<? extends BasePage> getRootNavPageClass() {
|
| | | return UsersPage.class;
|
| | | return TeamsPage.class;
|
| | | }
|
| | |
|
| | | protected void setupPage(final TeamModel teamModel) {
|
| | |
| | | teamModel.name));
|
| | | }
|
| | | // back to users page
|
| | | setResponsePage(UsersPage.class);
|
| | | setResponsePage(TeamsPage.class);
|
| | | }
|
| | | };
|
| | |
|
| | |
| | |
|
| | | @Override
|
| | | public void onSubmit() {
|
| | | setResponsePage(UsersPage.class);
|
| | | setResponsePage(TeamsPage.class);
|
| | | }
|
| | | };
|
| | | cancel.setDefaultFormProcessing(false);
|
| | |
| | | <body>
|
| | | <wicket:extend>
|
| | | <div class="container">
|
| | | <h2>Empty Repository</h2>
|
| | | <p></p>
|
| | | <div class="row">
|
| | | <div class="span10">
|
| | | <div class="alert alert-success">
|
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> is an empty repository and can not be viewed by Gitblit.
|
| | | <p></p> |
| | | Please push some commits to <span wicket:id="pushurl"></span>
|
| | | <p></p>
|
| | | <hr/>
|
| | | After you have pushed commits you may <b>refresh</b> this page to view your repository.
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | <div class="markdown">
|
| | | <div class="row">
|
| | | <div class="span10 offset1"> |
| | | <h3><center>Empty Repository</center></h3>
|
| | | <div class="alert alert-info">
|
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> is an empty repository and can not be viewed by Gitblit.
|
| | | <p></p> |
| | | Please push some commits to <span wicket:id="pushurl"></span>
|
| | | <hr/>
|
| | | After you have pushed commits you may <b>refresh</b> this page to view your repository.
|
| | | </div>
|
| | |
|
| | | <h3>Git Command-Line Syntax</h3>
|
| | | <span style="padding-bottom:5px;">If you do not have a local Git repository, then you should clone this repository, commit some files, and then push your commits back to Gitblit.</span>
|
| | | <p></p>
|
| | | <pre style="padding: 5px 30px;" wicket:id="cloneSyntax"></pre>
|
| | | <p></p>
|
| | | <span style="padding-bottom:5px;">If you already have a local Git repository with commits, then you may add this repository as a remote and push to it.</span>
|
| | | <p></p>
|
| | | <pre wicket:id="remoteSyntax" style="padding: 5px 30px;"></pre>
|
| | | <p></p>
|
| | | <span style="padding-bottom:5px;">If your repository is meant to be kept in sync with an upstream repository, then you may add it.</span>
|
| | | <p></p>
|
| | | <pre wicket:id="upstreamSyntax" style="padding: 5px 30px;"></pre>
|
| | | <p></p>
|
| | | <h3>Learn Git</h3>
|
| | | If you are unsure how to use this information, consider reviewing the <a href="http://book.git-scm.com">Git Community Book</a> or <a href="http://progit.org/book" target="_blank">Pro Git</a> for a better understanding on how to use Git.
|
| | | <p></p>
|
| | | <h3><center>Create a new repository on the command-line</center></h3>
|
| | |
|
| | | <pre wicket:id="createSyntax"></pre>
|
| | |
|
| | | <h3><center>Push an existing repository from the command-line</center></h3>
|
| | |
|
| | | <pre wicket:id="existingSyntax"></pre>
|
| | | |
| | | <div class="span8 offset1">
|
| | | <h2><center>Learn Git</center></h2>
|
| | | <p>If you are unsure how to use this information, consider reviewing the <a href="http://book.git-scm.com">Git Community Book</a> for a better understanding on how to use Git.</p>
|
| | |
|
| | | <h4>Open Source Git Clients</h4>
|
| | | <ul>
|
| | | <li><a href="http://git-scm.com">Git</a> - the official, command-line Git</li>
|
| | | <li><a href="http://tortoisegit.googlecode.com">TortoiseGit</a> - Windows file explorer integration (requires official, command-line Git)</li>
|
| | | <li><a href="http://eclipse.org/egit">Eclipse/EGit</a> - Git for the Eclipse IDE (based on JGit, like Gitblit)</li>
|
| | | <li><a href="https://code.google.com/p/gitextensions/">Git Extensions</a> - C# frontend for Git that features Windows Explorer and Visual Studio integration</li>
|
| | | <li><a href="http://rowanj.github.io/gitx/">GitX-dev</a> - a Mac OS X Git client</li> |
| | | </ul>
|
| | | <p></p>
|
| | | <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>
|
| | | <ul>
|
| | | <li><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a> - A Java Git and Mercurial client for Windows, Mac, and Linux</li>
|
| | | <li><a href="http://www.sourcetreeapp.com/">SourceTree</a> - A free Git and Mercurial client for Windows & Mac</li>
|
| | | <li><a href="http://www.git-tower.com/">Tower</a> - a Mac OS X Git client</li>
|
| | | </ul>
|
| | | <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>
|
| | |
| | | */
|
| | | package com.gitblit.wicket.pages;
|
| | |
|
| | | import java.text.MessageFormat;
|
| | | import java.util.List;
|
| | |
|
| | | import javax.servlet.http.HttpServletRequest;
|
| | |
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.RepositoryUrlPanel;
|
| | |
|
| | | public class EmptyRepositoryPage extends RootPage {
|
| | | public class EmptyRepositoryPage extends RepositoryPage {
|
| | |
|
| | | public EmptyRepositoryPage(PageParameters params) {
|
| | | super(params);
|
| | |
| | | throw new GitblitRedirectException(SummaryPage.class, params);
|
| | | }
|
| | |
|
| | | setupPage(repositoryName, getString("gb.emptyRepository"));
|
| | |
|
| | | UserModel user = GitBlitWebSession.get().getUser();
|
| | | if (user == null) {
|
| | | user = UserModel.ANONYMOUS;
|
| | |
| | | RepositoryUrl primaryUrl = repositoryUrls.size() == 0 ? null : repositoryUrls.get(0);
|
| | | String url = primaryUrl != null ? primaryUrl.url : "";
|
| | |
|
| | | String createSyntax = readResource("create_git.md").replace("${primaryUrl}", url);
|
| | | String existingSyntax = readResource("existing_git.md").replace("${primaryUrl}", url);
|
| | |
|
| | | add(new Label("repository", repositoryName));
|
| | | add(new RepositoryUrlPanel("pushurl", false, user, repository));
|
| | | add(new Label("cloneSyntax", MessageFormat.format("git clone {0}", url)));
|
| | | add(new Label("remoteSyntax", MessageFormat.format("git remote add origin {0}\ngit push -u origin --all\ngit push -u origin --tags", url)));
|
| | | add(new Label("upstreamSyntax", "git remote add upstream <upstream repository url>"));
|
| | | add(new Label("createSyntax", createSyntax));
|
| | | add(new Label("existingSyntax", existingSyntax));
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected Class<? extends BasePage> getRootNavPageClass() {
|
| | | return RepositoriesPage.class;
|
| | | protected String getPageName() {
|
| | | return getString("gb.summary");
|
| | | }
|
| | | }
|
New file |
| | |
| | | <!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>Leeres Repository</center></h3>
|
| | | <div class="alert alert-info">
|
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> ist ein leeres Repository und kann von Gitblit nicht angezeigt werden.
|
| | | <p></p> |
| | | Bitte pushen Sie einige Commits nach <span wicket:id="pushurl"></span>
|
| | | <hr/>
|
| | | Nachdem Sie Commits gepusht haben, können Sie diese Seite <b>aktualisieren</b>, um Ihr Repository anzuzeigen.
|
| | | </div>
|
| | | |
| | | <h3><center>Neues Respository auf der Kommandozeile erstellen</center></h3>
|
| | |
|
| | | <pre wicket:id="createSyntax"></pre>
|
| | |
|
| | | <h3><center>Ein existierendes Repository von der Kommandozeile pushen</center></h3>
|
| | |
|
| | | <pre wicket:id="existingSyntax"></pre>
|
| | | |
| | | <div class="span8 offset1">
|
| | | <h2><center>Git lernen</center></h2>
|
| | | <p>Falls Sie unsicher sind, was Sie mit diesen Informationen anfangen sollen, können Sie sich das <a href="http://git-scm.com/book/de">Git Community Buch</a> anschauen, um ein besseres Verständnis über die Verwendung von Git aufzubauen.</p>
|
| | |
|
| | | <h4>Open Source Git Clients</h4>
|
| | | <table>
|
| | | <tbody>
|
| | | <tr><td><a href="http://git-scm.com">Git</a></td><td>der offizielle Kommandozeilen-Git-Client</td></tr>
|
| | | <tr><td><a href="http://tortoisegit.googlecode.com">TortoiseGit</a></td><td>Windows Datei Explorer Integration (erfordert den offiziellen Kommandozeilen-Client)</td></tr>
|
| | | <tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a></td><td>Git für die Eclipse IDE (basiert auf JGit, ebenso wie Gitblit)</td></tr>
|
| | | <tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a></td><td>C# Frontend für Git mit Windows Explorer und Visual Studio Integration</td></tr>
|
| | | <tr><td><a href="http://rowanj.github.io/gitx/">GitX-dev</a></td><td>ein Mac OS X Git Client</td></tr>
|
| | | </tbody> |
| | | </table>
|
| | |
|
| | | <h4>Kommerzielle/Closed-Source Git Clients</h4>
|
| | | <table>
|
| | | <tbody>
|
| | | <tr><td><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a></td><td>Ein Java Git und Mercurial Client für Windows, Mac und Linux</td></tr>
|
| | | <tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a></td><td>Ein freier Git und Mercurial Client für Windows und Mac</td></tr>
|
| | | <tr><td><a href="http://www.git-tower.com/">Tower</a></td><td>Ein Mac OS X Git Client</td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </wicket:extend> |
| | | </body>
|
| | | </html>
|
| | |
| | | <body>
|
| | | <wicket:extend>
|
| | | <div class="container">
|
| | | <h2>Repositorio Vacío</h2>
|
| | | <p></p>
|
| | | <div class="row">
|
| | | <div class="span7">
|
| | | <div class="alert alert-success">
|
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> es un repositorio vacío y no puede ser visto en Gitblit.
|
| | | <p></p>
|
| | | Por favor, empuja algunas consignas a <span wicket:id="pushurl"></span>
|
| | | <p></p>
|
| | | <hr/>
|
| | | Después de empujar tus consignas puedes <b>refrescar</b> ésta página para ver tu repositorio.
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | <div class="markdown">
|
| | | <div class="row">
|
| | | <div class="span10 offset1"> |
| | | <h3><center>Repositorio Vacío</center></h3>
|
| | | <div class="alert alert-info">
|
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> es un repositorio vacío y no puede ser visto en Gitblit.
|
| | | <p></p> |
| | | Por favor, empuja algunas consignas a <span wicket:id="pushurl"></span>
|
| | | <hr/>
|
| | | Después de empujar tus consignas puedes <b>refrescar</b> ésta página para ver tu repositorio.
|
| | | </div>
|
| | |
|
| | | <h3>Sintaxis de la Línea de Comandos de Git</h3>
|
| | | <span style="padding-bottom:5px;">Si no tienes un repositiorio local Git, puedes clonar éste, consignar algunos archivos, y después empujar las consignas de vuelta a Gitblit.</span>
|
| | | <p></p>
|
| | | <pre style="padding: 5px 30px;" wicket:id="cloneSyntax"></pre>
|
| | | <p></p>
|
| | | <span style="padding-bottom:5px;">Si ya tienes un repositorio local Git con algunas consignas, puedes añadir éste como remoto y empujar desde allí.</span>
|
| | | <p></p>
|
| | | <pre style="padding: 5px 30px;" wicket:id="remoteSyntax"></pre>
|
| | | <span style="padding-bottom:5px;">Si el repositorio está pensado para mantenerse sincronizado con otro repositorio corriente-arriba, entonces puedes añadirlo.</span>
|
| | | <p></p>
|
| | | <pre wicket:id="upstreamSyntax" style="padding: 5px 30px;"></pre>
|
| | | <p></p>
|
| | | <h3>Aprender sobre Git</h3>
|
| | | Si no estás seguro de como usar esta información, échale un vistazo al <a href="http://book.git-scm.com">Libro de la cominidad Git</a> o <a href="http://progit.org/book" target="_blank">Pro Git</a> para una mejor compresión de como usar Git.
|
| | | <p></p>
|
| | | <h3><center>Create a new repository on the command-line</center></h3>
|
| | |
|
| | | <pre wicket:id="createSyntax"></pre>
|
| | |
|
| | | <h3><center>Push an existing repository from the command-line</center></h3>
|
| | |
|
| | | <pre wicket:id="existingSyntax"></pre>
|
| | |
|
| | | <div class="span8 offset1">
|
| | | <h2><center>Aprender sobre Git</center></h2>
|
| | | <p>Si no estás seguro de como usar esta información, échale un vistazo al <a href="http://book.git-scm.com/es">Libro de la cominidad Git</a> para una mejor compresión de como usar Git.</p>
|
| | |
|
| | | <h4>Clientes Git de Código abierto.</h4>
|
| | | <ul>
|
| | | <li><a href="http://git-scm.com">Git</a> - El Git oficial en línea de comandos</li>
|
| | | <li><a href="http://tortoisegit.googlecode.com">TortoiseGit</a> - Explorador de archivos integrado en Windows (necesita Git oficial en línea de comandos)</li>
|
| | | <li><a href="http://eclipse.org/egit">Eclipse/EGit</a> - Git para el IDE de Eclipse (basado en JGit, como Gitblit)</li>
|
| | | <li><a href="https://code.google.com/p/gitextensions/">Git Extensions</a> - Interfaz de usuario gráfico Git en C# con integración en IE y en Visual Studio</li>
|
| | | <li><a href="http://rowanj.github.io/gitx/">GitX-dev</a> - Cliente Git para Mac OS X</li> |
| | | </ul>
|
| | | <p></p>
|
| | | <table>
|
| | | <tbody>
|
| | | <tr><td><a href="http://git-scm.com">Git</a></td><td>El Git oficial en línea de comandos</td></tr>
|
| | | <tr><td><a href="http://tortoisegit.googlecode.com">TortoiseGit</a></td><td>Explorador de archivos integrado en Windows (necesita Git oficial en línea de comandos)</td></tr>
|
| | | <tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a></td><td>Git para el IDE de Eclipse (basado en JGit, como Gitblit)</td></tr>
|
| | | <tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a></td><td>Interfaz de usuario gráfico Git en C# con integración en IE y en Visual Studio</td></tr>
|
| | | <tr><td><a href="http://rowanj.github.io/gitx/">GitX-dev</a></td><td>Cliente Git para Mac OS X</td></tr>
|
| | | </tbody> |
| | | </table>
|
| | |
|
| | | <h4>Clientes Git comerciales</h4>
|
| | | <ul>
|
| | | <li><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a> - aplicación Java (necesita Git oficial en línea de comandos)</li>
|
| | | <li><a href="http://www.sourcetreeapp.com/">SourceTree</a> - Un cliente Git gratuito para Mac, Mercurial, y SVN</li>
|
| | | <li><a href="http://www.git-tower.com/">Tower</a> - Cliente Git para Mac OS X</li>
|
| | | </ul>
|
| | | </div> |
| | | <table>
|
| | | <tbody>
|
| | | <tr><td><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a></td><td>aplicación Java (necesita Git oficial en línea de comandos)</td></tr>
|
| | | <tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a></td><td>Un cliente Git gratuito para Mac, Mercurial, y SVN</td></tr>
|
| | | <tr><td><a href="http://www.git-tower.com/">Tower</a></td><td>Cliente Git para Mac OS X</td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </wicket:extend>
|
| | | </body>
|
| | | </html>
|
New file |
| | |
| | | <!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>Repository vuoto</center></h3>
|
| | | <div class="alert alert-info">
|
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> è vuoto e non può essere visualizzato con Gitblit.
|
| | | <p></p> |
| | | Per favore effettua il push di alcuni commit su <span wicket:id="pushurl"></span>
|
| | | <hr/>
|
| | | Dopo il push <b>ricarica</b> questa pagina per vedere il contenuto del repository.
|
| | | </div>
|
| | | |
| | | <h3><center>Crea un nuovo repository da riga di comando</center></h3>
|
| | |
|
| | | <pre wicket:id="createSyntax"></pre>
|
| | |
|
| | | <h3><center>Effettua il push da riga di comando</center></h3>
|
| | |
|
| | | <pre wicket:id="existingSyntax"></pre>
|
| | | |
| | | <div class="span8 offset1">
|
| | | <h2><center>Impara a usare Git</center></h2>
|
| | | <p>Se non sei sicuro di quello che stai facendo, prova a leggere <a href="http://book.git-scm.com/it">Git Community Book</a> in italiano per una miglior comprensione dell'utilizzo di Git.</p>
|
| | |
|
| | | <h4>Applicazioni client Git open source</h4>
|
| | | <table>
|
| | | <tbody>
|
| | | <tr><td><a href="http://git-scm.com">Git</a></td><td>la versione ufficiale di Git, da riga di comando</td></tr>
|
| | | <tr><td><a href="http://tortoisegit.googlecode.com">TortoiseGit</a></td><td>Integrazione per Windows Explorer (richiede la versione ufficiale di Git da riga di comando)</td></tr>
|
| | | <tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a></td><td>Git per ambienti di sviluppo basati su Eclipse (basato su JGit, come Gitblit)</td></tr>
|
| | | <tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a></td><td>applicazione C# che integra Git in Windows Explorer e Visual Studio</td></tr>
|
| | | <tr><td><a href="http://rowanj.github.io/gitx/">GitX-dev</a></td><td>un client Git per Mac OS X</td></tr>
|
| | | </tbody> |
| | | </table>
|
| | |
|
| | | <h4>Applicazioni client commerciali/non open source</h4>
|
| | | <table>
|
| | | <tbody>
|
| | | <tr><td><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a></td><td>Un client Git e Mercurial scritto in Java per Windows, Mac, and Linux</td></tr>
|
| | | <tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a></td><td>Un client Git e Mercurial gratuito per Windows & Mac</td></tr>
|
| | | <tr><td><a href="http://www.git-tower.com/">Tower</a></td><td>Un client Git per Mac OS X</td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </wicket:extend> |
| | | </body>
|
| | | </html>
|
| | |
| | | <body> |
| | | <wicket:extend> |
| | | <div class="container"> |
| | | <h2>비어있는 저장소</h2> |
| | | <p></p> |
| | | <div class="row"> |
| | | <div class="span10"> |
| | | <div class="alert alert-success"> |
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> 저장소는 비어 있어서 Gitblit 에서 볼 수 없습니다. |
| | | <p></p> |
| | | 이 Git url 에 커밋해 주세요. <span wicket:id="pushurl"></span> |
| | | <p></p> |
| | | <hr/> |
| | | After you have pushed commits you may <b>refresh</b> this page to view your repository. |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <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> |
| | | 이 Git url 에 커밋을 푸시하세요. <span wicket:id="pushurl"></span> |
| | | <hr/> |
| | | 커밋을 푸시한 후 이 페이지를 <b>새로고침</b>하면 저장소가 보여질 것입니다. |
| | | </div> |
| | | |
| | | <h3><center>커맨드라인에서 새 저장소 생성하기</center></h3> |
| | | |
| | | <p></p> |
| | | <h3>Git 명령어</h3> |
| | | <span style="padding-bottom:5px;">로컬 Git 저장소가 없다면, 이 저장소를 클론(clone) 한 후, 몇 파일을 커밋하고, 그 커밋을 Gitblit 에 푸시(push) 하세요.</span> |
| | | <p></p> |
| | | <pre style="padding: 5px 30px;" wicket:id="cloneSyntax"></pre> |
| | | <p></p> |
| | | <span style="padding-bottom:5px;">만약 커밋된 로컬 Git 저장소가 있다면, 다음과 같이 저장소에 리모트를 추가하고 푸시(push)할 수 있습니다.</span> |
| | | <p></p> |
| | | <pre style="padding: 5px 30px;" wicket:id="remoteSyntax"></pre> |
| | | <span style="padding-bottom:5px;">If your repository is meant to be kept in sync with an upstream repository, then you may add it.</span> |
| | | <p></p> |
| | | <pre wicket:id="upstreamSyntax" style="padding: 5px 30px;"></pre> |
| | | <p></p> |
| | | <h3>Git 배우기</h3> |
| | | 만약 사용법에 자신이 없다면, Git 사용법을 더 잘 이해하기 위해 |
| | | <a href="http://book.git-scm.com">Git Community Book</a> 또는 |
| | | <a href="http://progit.org/book" target="_blank">Pro Git</a>, |
| | | <a href="http://dogfeet.github.com/articles/2012/progit.html" target="_blank">Pro Git 한글</a> 을 볼 것을 고려해 보세요. |
| | | <p></p> |
| | | <h4>오픈소스 Git 클라이언트</h4> |
| | | <ul> |
| | | <li><a href="http://git-scm.com">Git</a> - 명령어 기반 공식 Git</li> |
| | | <li><a href="http://tortoisegit.googlecode.com">TortoiseGit</a> - 윈도의 파일 탐색기에 통합된 UI 클라이언트 (명령어 기반 공식 Git 필요)</li> |
| | | <li><a href="http://eclipse.org/egit">Eclipse/EGit</a> - 이클립스 IDE 플러그인 (Gitblit 과 같은 JGit 기반)</li> |
| | | <li><a href="https://code.google.com/p/gitextensions/">Git Extensions</a> - C# frontend for Git that features Windows Explorer and Visual Studio integration</li> |
| | | <li><a href="http://rowanj.github.io/gitx/">GitX-dev</a> - a Mac OS X Git client</li> |
| | | </ul> |
| | | <p></p> |
| | | <h4>유료 Git 클라이언트</h4> |
| | | <ul> |
| | | <li><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a> - 자바 어플리케이션 (명령어 기반 공식 Git 필요)</li> |
| | | <li><a href="http://www.sourcetreeapp.com/">SourceTree</a> - A free Mac Client for Git, Mercurial, and SVN</li> |
| | | <li><a href="http://www.git-tower.com/">Tower</a> - a Mac OS X Git client</li> |
| | | </ul> |
| | | <pre wicket:id="createSyntax"></pre> |
| | | |
| | | <h3><center>커맨드라인에서 기존의 저장소를 푸시하기</center></h3> |
| | | |
| | | <pre wicket:id="existingSyntax"></pre> |
| | | |
| | | <div class="span8 offset1"> |
| | | <h2><center>Git 배우기</center></h2> |
| | | <p>만약 사용법에 자신이 없다면, Git 사용법을 더 잘 이해하기 위해 |
| | | <a href="http://book.git-scm.com/ko">Git Community Book</a> 을 볼 것을 고려해 보세요.</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>윈도의 파일 탐색기에 통합된 UI 클라이언트 (명령어 기반 공식 Git 필요)</td></tr> |
| | | <tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a></td><td>이클립스 IDE 플러그인 (Gitblit 과 같은 JGit 기반)</td></tr> |
| | | <tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a></td><td>윈도 탐색기와 비주얼스튜디어를 위한 C#으로 개발된 기능</td></tr> |
| | | <tr><td><a href="http://rowanj.github.io/gitx/">GitX-dev</a></td><td>맥 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>자바 어플리케이션 (명령어 기반 공식 Git 필요)</td></tr> |
| | | <tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a></td><td>윈도와 맥에서 가능한 Git 과 Mercurial용 무료 클라이언트</td></tr> |
| | | <tr><td><a href="http://www.git-tower.com/">Tower</a></td><td>맥 OS X 용 Git 클라이언트</td></tr> |
| | | </tbody> |
| | | </table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </wicket:extend> |
| | | </body> |
| | |
| | | <body>
|
| | | <wicket:extend>
|
| | | <div class="container">
|
| | | <h2>Lege Repository</h2>
|
| | | <p></p>
|
| | | <div class="row">
|
| | | <div class="span10">
|
| | | <div class="alert alert-success">
|
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> is een lege repository en kan niet bekeken worden door Gitblit.
|
| | | <p></p> |
| | | Push alstublieft een paar commits naar <span wicket:id="pushurl"></span>
|
| | | <p></p>
|
| | | <hr/>
|
| | | Nadat u een commits gepushed heeft, kunt u deze pagina <b>verversen</b> om uw repository te bekijken.
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | <div class="markdown">
|
| | | <div class="row">
|
| | | <div class="span10 offset1"> |
| | | <h3><center>Lege Repository</center></h3>
|
| | | <div class="alert alert-info">
|
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> is een lege repository en kan niet bekeken worden door Gitblit.
|
| | | <p></p> |
| | | Push alstublieft een paar commits naar <span wicket:id="pushurl"></span>
|
| | | <hr/>
|
| | | Nadat u een commits gepushed heeft, kunt u deze pagina <b>verversen</b> om uw repository te bekijken.
|
| | | </div>
|
| | |
|
| | | <h3>Git Command-Line Syntax</h3>
|
| | | <span style="padding-bottom:5px;">Als u geen lokale Git repository heeft, kunt u deze repository clonen, er bestanden naar committen en dan uw commits terug pushen naar Gitblit.</span>
|
| | | <p></p>
|
| | | <pre style="padding: 5px 30px;" wicket:id="cloneSyntax"></pre>
|
| | | <p></p>
|
| | | <span style="padding-bottom:5px;">Als u al een lokale Git repository met commits heeft, kunt u deze repository als een remote toevoegen en er naar pushen.</span>
|
| | | <p></p>
|
| | | <pre wicket:id="remoteSyntax" style="padding: 5px 30px;"></pre>
|
| | | <p></p>
|
| | | <span style="padding-bottom:5px;">Indien uw repository bedoeld is om synchroon gehouden te worden met een upstream repository, dan kunt u deze toevoegen.</span>
|
| | | <p></p>
|
| | | <pre wicket:id="upstreamSyntax" style="padding: 5px 30px;"></pre>
|
| | | <p></p>
|
| | | <h3>Leer Git</h3>
|
| | | Als u niet goed weet wat u met deze informatie aan moet, raden we u aan om het <a href="http://book.git-scm.com">Git Community Book</a> of <a href="http://progit.org/book" target="_blank">Pro Git</a> te bestuderen voor een beter begrip over hoe u Git kunt gebruiken.
|
| | | <p></p>
|
| | | <h4>Open Source Git Clients</h4>
|
| | | <ul>
|
| | | <li><a href="http://git-scm.com">Git</a> - de officiele, command-line Git</li>
|
| | | <li><a href="http://tortoisegit.googlecode.com">TortoiseGit</a> - Windows bestandsverkenner ingetratie (officiele command-line Git is wel nodig)</li>
|
| | | <li><a href="http://eclipse.org/egit">Eclipse/EGit</a> - Git voor de Eclipse IDE (gebaseerd op JGit, zoals Gitblit)</li>
|
| | | <li><a href="https://code.google.com/p/gitextensions/">Git Extensions</a> - C# frontend voor Git met Windows Explorer en Visual Studio integratie</li>
|
| | | <li><a href="http://rowanj.github.io/gitx/">GitX-dev</a> - een Mac OS X Git client</li> |
| | | </ul>
|
| | | <p></p>
|
| | | <h4>Commercial/Closed-Source Git Clients</h4>
|
| | | <ul>
|
| | | <li><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a> - Een Java Git, Mercurial, en SVN client applicatie (officiele command-line Git is wel nodig)</li>
|
| | | <li><a href="http://www.sourcetreeapp.com/">SourceTree</a> - Een gratis Mac Client voor Git, Mercurial, en SVN</li>
|
| | | <li><a href="http://www.git-tower.com/">Tower</a> - een Mac OS X Git client</li>
|
| | | </ul>
|
| | | <h3><center>Maak een nieuwe repositorie via de command-line</center></h3>
|
| | |
|
| | | <pre wicket:id="createSyntax"></pre>
|
| | |
|
| | | <h3><center>Push een bestaande repositorie vanaf de command-line</center></h3>
|
| | |
|
| | | <pre wicket:id="existingSyntax"></pre>
|
| | |
|
| | | <div class="span8 offset1">
|
| | | <h2><center>Leer Git</center></h2>
|
| | | <p>Als u niet goed weet wat u met deze informatie aan moet, raden we u aan om het <a href="http://book.git-scm.com/nl">Git Community Book</a> te bestuderen voor een beter begrip over hoe u Git kunt gebruiken.</p>
|
| | |
|
| | | <h4>Open Source Git Programma's</h4>
|
| | | <table>
|
| | | <tbody>
|
| | | <tr><td><a href="http://git-scm.com">Git</a></td><td>de officiele, command-line Git</td></tr>
|
| | | <tr><td><a href="http://tortoisegit.googlecode.com">TortoiseGit</a></td><td>Windows bestandsverkenner integratie (officiele command-line Git is wel nodig)</td></tr>
|
| | | <tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a></td><td>Git voor de Eclipse IDE (gebaseerd op JGit, zoals Gitblit)</td></tr>
|
| | | <tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a></td><td>C# frontend voor Git met Windows Explorer en Visual Studio integratie</td></tr>
|
| | | <tr><td><a href="http://rowanj.github.io/gitx/">GitX-dev</a></td><td>een Mac OS X Git client</td></tr>
|
| | | </tbody> |
| | | </table>
|
| | |
|
| | | <h4>Commerciele/Closed-Source Git Programma's</h4>
|
| | | <table>
|
| | | <tbody>
|
| | | <tr><td><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a></td><td>Een Java Git, Mercurial, en SVN client applicatie (officiele command-line Git is wel nodig)</td></tr>
|
| | | <tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a></td><td>Een gratis Mac Client voor Git en Mercurial</td></tr>
|
| | | <tr><td><a href="http://www.git-tower.com/">Tower</a></td><td>een Mac OS X Git client</td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </wicket:extend>
|
| | | </body>
|
New file |
| | |
| | | <!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>Tomt Repository</center></h3> |
| | | <div class="alert alert-info"> |
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> er et tomt repository som ikke kan vises av Gitblit. |
| | | <p></p> |
| | | Vennligst push noen endringer inn til <span wicket:id="pushurl"></span> |
| | | <hr/> |
| | | Etter at du har pushet noen endringer, kan du <b>oppfriske</b> denne siden for \u00e5 se repositoriet. |
| | | </div> |
| | | |
| | | <h3><center>Opprett et nytt repository fra kommandolinjen</center></h3> |
| | | |
| | | <pre wicket:id="createSyntax"></pre> |
| | | |
| | | <h3><center>Push et eksisternde repository fra kommandolinjen</center></h3> |
| | | |
| | | <pre wicket:id="existingSyntax"></pre> |
| | | |
| | | <div class="span8 offset1"> |
| | | <h2><center>L\u00e6r Git</center></h2> |
| | | <p>Hvis du er usikker p\u00e5 hvordan du kan benytte denne informasjonen, vurder \u00e5 lese <a href="http://book.git-scm.com">Git Community Book</a> eller <a href="http://progit.org/book" target="_blank">Pro Git</a> for \u00e5 f\u00e5 en bedre forst\u00e5else av hvordan du kan bruke Git. </p> |
| | | |
| | | <h4>Open Source Git Clients</h4> |
| | | <table> |
| | | <tbody> |
| | | <tr><td>a href="http://git-scm.com">Git</a> - den offisielle, kommando-linje git</td></tr> |
| | | <tr><td>a href="http://tortoisegit.googlecode.com">TortoiseGit</a> - Windows filutforsker integrasjon (krever den offisielle kommando-linje git versjonen installert</td></tr> |
| | | <tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a> - Git for Eclipse IDE (basert p\u00e5 JGit, akkurat som Gitblit er)</tr> |
| | | <tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a> - En C# frontend for Git som integrerer med filutforskeren og Visual Studio.</td></tr> |
| | | <tr><td><a href="http://rowanj.github.io/gitx/">GitX-dev</a> - En git klient for OS X</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> - En Git og Mercurial klient for Windows, Mac, og Linux</td></tr> |
| | | <tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a> - En gratis Git og Mercurial klient for Windows og Mac</td></tr> |
| | | <tr><td>a href="http://www.git-tower.com/">Tower</a> - En git klient for Mac OS X </td></tr> |
| | | </tbody> |
| | | </table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </wicket:extend> |
| | | </body> |
| | | </html> |
| | |
| | | <body> |
| | | <wicket:extend> |
| | | <div class="container"> |
| | | <h2>Puste repozytorium</h2> |
| | | <p></p> |
| | | <div class="row"> |
| | | <div class="span10"> |
| | | <div class="alert alert-success"> |
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> jest pustym repozytorium i nie może być zaprezentowane przez Gitblit. |
| | | <p></p> |
| | | Wgraj, poprzez push, dowolne zmiany do lokalizacji <span wicket:id="pushurl"></span> |
| | | <p></p> |
| | | <hr/> |
| | | Po wgraniu zmian <b>odśwież</b> stronę, aby podejrzeć repozytorium. |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="markdown"> |
| | | <div class="row"> |
| | | <div class="span10 offset1"> |
| | | <h3><center>Puste repozytorium</center></h3> |
| | | <div class="alert alert-info"> |
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> jest pustym repozytorium i nie może być zaprezentowane przez Gitblit. |
| | | <p></p> |
| | | Wgraj, poprzez push, dowolne zmiany do lokalizacji <span wicket:id="pushurl"></span> |
| | | <hr/> |
| | | Po wgraniu zmian <b>odśwież</b> stronę, aby podejrzeć repozytorium. |
| | | </div> |
| | | |
| | | <h3>Składnia linii poleceń GITa</h3> |
| | | <span style="padding-bottom:5px;">Jeśli nie posiadasz lokalnego repozytorium GITa to sklonuj to repozytorium, wgraj dowolne pliki, a następnie wyślij poprzez push zmiany na Gitblit.</span> |
| | | <p></p> |
| | | <pre style="padding: 5px 30px;" wicket:id="cloneSyntax"></pre> |
| | | <p></p> |
| | | <span style="padding-bottom:5px;">Gdy posiadasz lokalne repozytorium GITa z dowolnymi zmianami, to możesz dodać to repozytorium jako remote i wysłać do niego zmiany poprzez push.</span> |
| | | <p></p> |
| | | <pre style="padding: 5px 30px;" wicket:id="remoteSyntax"></pre> |
| | | <span style="padding-bottom:5px;">If your repository is meant to be kept in sync with an upstream repository, then you may add it.</span> |
| | | <p></p> |
| | | <pre wicket:id="upstreamSyntax" style="padding: 5px 30px;"></pre> |
| | | <p></p> |
| | | <h3>Nauka GITa</h3> |
| | | Jeżeli powyższe informacje są dla Ciebie niezrozumiałe, zapoznaj się z książką <a href="http://git-scm.com/book/pl" target="_blank">Pro Git - Wersja PL</a> dla lepszego zrozumienia, jak poprawnie używać GITa. |
| | | <p></p> |
| | | <h3><center>Create a new repository on the command-line</center></h3> |
| | | |
| | | <pre wicket:id="createSyntax"></pre> |
| | | |
| | | <h3><center>Push an existing repository from the command-line</center></h3> |
| | | |
| | | <pre wicket:id="existingSyntax"></pre> |
| | | |
| | | <div class="span8 offset1"> |
| | | <h2><center>Nauka GITa</center></h2> |
| | | <p>Jeżeli powyższe informacje są dla Ciebie niezrozumiałe, zapoznaj się z książką <a href="http://git-scm.com/book/pl" target="_blank">Pro Git - Wersja PL</a> dla lepszego zrozumienia, jak poprawnie używać GITa.</p> |
| | | |
| | | <h4>Darmowi klienci GITa</h4> |
| | | <ul> |
| | | <li><a href="http://git-scm.com">Git</a> - Oficjalny klient, dostępny przez linię poleceń</li> |
| | | <li><a href="http://tortoisegit.googlecode.com">TortoiseGit</a> - Rozszerzenie eksploratora Windows (wymaga oficjalnego, dostępnego przez linię poleceń klienta)</li> |
| | | <li><a href="http://eclipse.org/egit">Eclipse/EGit</a> - GIT dla edytora Eclipse (oparty o JGit, podobnie jak Gitblit)</li> |
| | | <li><a href="https://code.google.com/p/gitextensions/">Git Extensions</a> - napisana w C# fasada na GIT, udostępniająca integrację dla Windows Explorer oraz Visual Studio</li> |
| | | <li><a href="http://rowanj.github.io/gitx/">GitX-dev</a> - klient GIT na Mac OS X</li> |
| | | </ul> |
| | | <p></p> |
| | | <table> |
| | | <tbody> |
| | | <tr><td><a href="http://git-scm.com">Git</a></td><td>Oficjalny klient, dostępny przez linię poleceń</td></tr> |
| | | <tr><td><a href="http://tortoisegit.googlecode.com">TortoiseGit</a></td><td>Rozszerzenie eksploratora Windows (wymaga oficjalnego, dostępnego przez linię poleceń klienta)</td></tr> |
| | | <tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a></td><td>GIT dla edytora Eclipse (oparty o JGit, podobnie jak Gitblit)</td></tr> |
| | | <tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a></td><td>napisana w C# fasada na GIT, udostępniająca integrację dla Windows Explorer oraz Visual Studio</td></tr> |
| | | <tr><td><a href="http://rowanj.github.io/gitx/">GitX-dev</a></td><td>klient GIT na Mac OS X</td></tr> |
| | | </tbody> |
| | | </table> |
| | | |
| | | <h4>Komercyjni klienci GITa</h4> |
| | | <ul> |
| | | <li><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a> - aplikacja napisana w Javie (wymaga oficjalnego, dostępnego przez linię poleceń klienta)</li> |
| | | <li><a href="http://www.sourcetreeapp.com/">SourceTree</a> - darmowy klient GIT, Mercurial i SVN na Mac OS X</li> |
| | | <li><a href="http://www.git-tower.com/">Tower</a> - klient GIT na Mac OS X</li> |
| | | </ul> |
| | | <table> |
| | | <tbody> |
| | | <tr><td><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a></td><td>aplikacja napisana w Javie (wymaga oficjalnego, dostępnego przez linię poleceń klienta)</td></tr> |
| | | <tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a></td><td>darmowy klient GIT, Mercurial i SVN na Mac OS X</td></tr> |
| | | <tr><td><a href="http://www.git-tower.com/">Tower</a></td><td>klient GIT na Mac OS X</td></tr> |
| | | </tbody> |
| | | </table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </wicket:extend> |
| | | </body> |
| | |
| | | <body>
|
| | | <wicket:extend>
|
| | | <div class="container">
|
| | | <h2>Repositório Vazio</h2>
|
| | | <p></p>
|
| | | <div class="row">
|
| | | <div class="span10">
|
| | | <div class="alert alert-success">
|
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> é um repositório vazio e não pode ser visualizado pelo Gitblit.
|
| | | <p></p> |
| | | Por favor faça o push de alguns commits para <span wicket:id="pushurl"></span>
|
| | | <p></p>
|
| | | <hr/>
|
| | | Depois de ter feito push você poderá <b>atualizar</b> esta página para visualizar seu repositório.
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | <div class="markdown">
|
| | | <div class="row">
|
| | | <div class="span10 offset1"> |
| | | <h3><center>Repositório Vazio</center></h3>
|
| | | <div class="alert alert-info">
|
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> é um repositório vazio e não pode ser visualizado pelo Gitblit.
|
| | | <p></p> |
| | | Por favor faça o push de alguns commits para <span wicket:id="pushurl"></span>
|
| | | <hr/>
|
| | | Depois de ter feito push você poderá <b>atualizar</b> esta página para visualizar seu repositório.
|
| | | </div>
|
| | |
|
| | | <h3>Sintaxe dos comandos do Git</h3>
|
| | | <span style="padding-bottom:5px;">Se você ainda não tem um repositório local do Git, então você deve primeiro clonar este repositório, fazer commit de alguns arquivos e então fazer push desses commits para o Gitblit.</span>
|
| | | <p></p>
|
| | | <pre style="padding: 5px 30px;" wicket:id="cloneSyntax"></pre>
|
| | | <p></p>
|
| | | <span style="padding-bottom:5px;">Se você já tem um repositório Git local com alguns commits, então você deve adicionar este repositório como uma referência remota e então fazer push.</span>
|
| | | <p></p>
|
| | | <pre wicket:id="remoteSyntax" style="padding: 5px 30px;"></pre>
|
| | | <span style="padding-bottom:5px;">If your repository is meant to be kept in sync with an upstream repository, then you may add it.</span>
|
| | | <p></p>
|
| | | <pre wicket:id="upstreamSyntax" style="padding: 5px 30px;"></pre>
|
| | | <p></p>
|
| | | <h3>Aprenda Git</h3>
|
| | | Se você estiver com dúvidas sobre como ultilizar essas informações, uma sugestão seria dar uma olhada no livro <a href="http://book.git-scm.com">Git Community Book</a> ou <a href="http://progit.org/book" target="_blank">Pro Git</a> para entender melhor como usar o Git.
|
| | | <p></p>
|
| | | <h3><center>Create a new repository on the command-line</center></h3>
|
| | |
|
| | | <pre wicket:id="createSyntax"></pre>
|
| | |
|
| | | <h3><center>Push an existing repository from the command-line</center></h3>
|
| | |
|
| | | <pre wicket:id="existingSyntax"></pre>
|
| | |
|
| | | <div class="span8 offset1">
|
| | | <h2><center>Aprenda Git</center></h2>
|
| | | <p>Se você estiver com dúvidas sobre como ultilizar essas informações, uma sugestão seria dar uma olhada no livro <a href="http://book.git-scm.com/pt-br">Git Community Book</a> para entender melhor como usar o Git.</p>
|
| | |
|
| | | <h4>Alguns clients do Git que são Open Source</h4>
|
| | | <ul>
|
| | | <li><a href="http://git-scm.com">Git</a> - o Git oficial através de linhas de comando</li>
|
| | | <li><a href="http://tortoisegit.googlecode.com">TortoiseGit</a> - Faz integração do Explorer do Windows com o Git (por isso requer o Git Oficial)</li>
|
| | | <li><a href="http://eclipse.org/egit">Eclipse/EGit</a> - Git para a IDE Eclipse (baseada no JGit, como o Gitblit)</li>
|
| | | <li><a href="https://code.google.com/p/gitextensions/">Git Extensions</a> - Interface (em C#) para o Git cuja a característica é a integração com o Windows Explorer e o Visual Studio</li>
|
| | | <li><a href="http://rowanj.github.io/gitx/">GitX-dev</a> - um Cliente do Git para Mac OS X</li> |
| | | </ul>
|
| | | <p></p>
|
| | | <table>
|
| | | <tbody>
|
| | | <tr><td><a href="http://git-scm.com">Git</a></td><td>o Git oficial através de linhas de comando</td></tr>
|
| | | <tr><td><a href="http://tortoisegit.googlecode.com">TortoiseGit</a></td><td>Faz integração do Explorer do Windows com o Git (por isso requer o Git Oficial)</td></tr>
|
| | | <tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a></td><td>Git para a IDE Eclipse (baseada no JGit, como o Gitblit)</td></tr>
|
| | | <tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a></td><td>Interface (em C#) para o Git cuja a característica é a integração com o Windows Explorer e o Visual Studio</td></tr>
|
| | | <tr><td><a href="http://rowanj.github.io/gitx/">GitX-dev</a></td><td>um Cliente do Git para Mac OS X</td></tr>
|
| | | </tbody> |
| | | </table>
|
| | |
|
| | | <h4>Clients do Git proprietários ou com Código Proprietário</h4>
|
| | | <ul>
|
| | | <li><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a> - Aplicação Client (em Java) para Git, Mercurial, e SVN (por isso requer o Git Oficial)</li>
|
| | | <li><a href="http://www.sourcetreeapp.com/">SourceTree</a> - Client gratuito para o Mac que suporta Git, Mercurial e SVN</li>
|
| | | <li><a href="http://www.git-tower.com/">Tower</a> - um Cliente do Git para Mac OS X</li>
|
| | | </ul>
|
| | | <table>
|
| | | <tbody>
|
| | | <tr><td><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a></td><td>Aplicação Client (em Java) para Git e Mercurial (por isso requer o Git Oficial)</td></tr>
|
| | | <tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a></td><td>Client gratuito para o Mac que suporta Git e Mercurial</td></tr>
|
| | | <tr><td><a href="http://www.git-tower.com/">Tower</a></td><td>um Cliente do Git para Mac OS X</td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </wicket:extend>
|
| | | </body>
|
| | |
| | | <body> |
| | | <wicket:extend> |
| | | <div class="container"> |
| | | <h2>空版本库</h2> |
| | | <p></p> |
| | | <div class="row"> |
| | | <div class="span10"> |
| | | <div class="alert alert-success"> |
| | | <span wicket:id="repository" style="font-weight: bold;">[repository]</span> 版本库目前为空。 |
| | | Gitblit 无法查看。 |
| | | <p></p> |
| | | 请往此网址进行推送 <span wicket:id="pushurl"></span> |
| | | <p></p> |
| | | <hr/> |
| | | 当你推送完毕后你可以 <b>刷新</b> 此页面重新查看您的版本库。 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <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> |
| | | 请往此网址进行推送 <span wicket:id="pushurl"></span> |
| | | <hr/> |
| | | 当你推送完毕后你可以 <b>刷新</b> 此页面重新查看您的版本库。 |
| | | </div> |
| | | |
| | | <h3>Git 命令行格式</h3> |
| | | <span style="padding-bottom:5px;">如果您没有本地 Git 版本库, 您可以克隆此版本库, 提交一些文件, 然后将您的提交推送回Gitblit。</span> |
| | | <p></p> |
| | | <pre style="padding: 5px 30px;" wicket:id="cloneSyntax"></pre> |
| | | <p></p> |
| | | <span style="padding-bottom:5px;">如果您已经有一个本地的提交过的版本库, 那么您可以将此版本库加为远程 |
| | | 版本库,并进行推送。</span> |
| | | <p></p> |
| | | <pre wicket:id="remoteSyntax" style="padding: 5px 30px;"></pre> |
| | | <span style="padding-bottom:5px;">If your repository is meant to be kept in sync with an upstream repository, then you may add it.</span> |
| | | <p></p> |
| | | <pre wicket:id="upstreamSyntax" style="padding: 5px 30px;"></pre> |
| | | <p></p> |
| | | <h3>学习 Git</h3> |
| | | 如果您不明白这些信息什么意思, 您可以参考 <a href="http://book.git-scm.com">Git Community Book</a> 或者 <a href="http://progit.org/book" target="_blank">Pro Git</a> 去更加深入的学习 Git 的用法。 |
| | | <p></p> |
| | | <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/zh">Git Community Book</a> 去更加深入的学习 Git 的用法。</p> |
| | | |
| | | <h4>开源 Git 客户端</h4> |
| | | <ul> |
| | | <li><a href="http://git-scm.com">Git</a> - 官方, 命令行版本 Git</li> |
| | | <li><a href="http://tortoisegit.googlecode.com">TortoiseGit</a> - 与 Windows 资源管理器集成 (需要官方, 命令行 Git 的支持)</li> |
| | | <li><a href="http://eclipse.org/egit">Eclipse/EGit</a> - Git for the Eclipse IDE (基于 JGit, 类似 Gitblit)</li> |
| | | <li><a href="https://code.google.com/p/gitextensions/">Git Extensions</a> - C# 版本的 Git 前端,与 Windows 资源管理器和 Visual Studio 集成</li> |
| | | <li><a href="http://rowanj.github.io/gitx/">GitX-dev</a> - Mac OS X Git 客户端</li> |
| | | </ul> |
| | | <p></p> |
| | | <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 资源管理器集成 (需要官方, 命令行 Git 的支持)</td></tr> |
| | | <tr><td><a href="http://eclipse.org/egit">Eclipse/EGit</a></td><td>Git for the Eclipse IDE (基于 JGit, 类似 Gitblit)</td></tr> |
| | | <tr><td><a href="https://code.google.com/p/gitextensions/">Git Extensions</a></td><td>C# 版本的 Git 前端,与 Windows 资源管理器和 Visual Studio 集成</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> |
| | | <ul> |
| | | <li><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a> - Java 版本的支持 Git, Mercurial 和 SVN 客户端应用 (需要官方, 命令行 Git 的支持)</li> |
| | | <li><a href="http://www.sourcetreeapp.com/">SourceTree</a> - 免费的 Mac Git Mercurial 以及 SVN 客户端, Mercurial, and SVN</li> |
| | | <li><a href="http://www.git-tower.com/">Tower</a> - Mac OS X Git 客户端</li> |
| | | </ul> |
| | | <table> |
| | | <tbody> |
| | | <tr><td><a href="http://www.syntevo.com/smartgithg">SmartGit/Hg</a></td><td>Java 版本的支持 Git, Mercurial 和 SVN 客户端应用 </td></tr> |
| | | <tr><td><a href="http://www.sourcetreeapp.com/">SourceTree</a></td><td>免费的 Mac Git Mercurial 以及 SVN 客户端 and 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> |
New file |
| | |
| | | <!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="row" style="padding-top:15px;min-height:500px;" > |
| | | <div class="tab-pane active" id="tickets"> |
| | | <!-- query controls --> |
| | | <div class="span3"> |
| | | <div class="hidden-phone"> |
| | | <div wicket:id="userTitlePanel"></div> |
| | | |
| | | <!-- search tickets form --> |
| | | <form class="form-search" style="margin: 10px 0px;" wicket:id="ticketSearchForm"> |
| | | <div class="input-append"> |
| | | <input type="text" class="input-medium search-query" style="border-radius: 14px 0 0 14px; padding-left: 14px;" id="ticketSearchBox" wicket:id="ticketSearchBox" value=""/> |
| | | <button class="btn" style="border-radius: 0 14px 14px 0px;margin-left:-5px;" type="submit"><i class="icon-search"></i></button> |
| | | </div> |
| | | </form> |
| | | |
| | | <!-- query list --> |
| | | <ul class="nav nav-list"> |
| | | <li class="nav-header"><wicket:message key="gb.queries"></wicket:message></li> |
| | | <li><a wicket:id="changesQuery"><i class="fa fa-code-fork"></i> <wicket:message key="gb.proposalTickets"></wicket:message></a></li> |
| | | <li><a wicket:id="bugsQuery"><i class="fa fa-bug"></i> <wicket:message key="gb.bugTickets"></wicket:message></a></li> |
| | | <li><a wicket:id="enhancementsQuery"><i class="fa fa-magic"></i> <wicket:message key="gb.enhancementTickets"></wicket:message></a></li> |
| | | <li><a wicket:id="tasksQuery"><i class="fa fa-ticket"></i> <wicket:message key="gb.taskTickets"></wicket:message></a></li> |
| | | <li><a wicket:id="questionsQuery"><i class="fa fa-question"></i> <wicket:message key="gb.questionTickets"></wicket:message></a></li> |
| | | <li wicket:id="userDivider" class="divider"></li> |
| | | <li><a wicket:id="createdQuery"><i class="fa fa-user"></i> <wicket:message key="gb.yourCreatedTickets"></wicket:message></a></li> |
| | | <li><a wicket:id="responsibleQuery"><i class="fa fa-user"></i> <wicket:message key="gb.yourAssignedTickets"></wicket:message></a></li> |
| | | <li><a wicket:id="watchedQuery"><i class="fa fa-eye"></i> <wicket:message key="gb.yourWatchedTickets"></wicket:message></a></li> |
| | | <li><a wicket:id="mentionsQuery"><i class="fa fa-comment"></i> <wicket:message key="gb.mentionsMeTickets"></wicket:message></a></li> |
| | | <li class="divider"></li> |
| | | <li><a wicket:id="resetQuery"><i class="fa fa-bolt"></i> <wicket:message key="gb.reset"></wicket:message></a></li> |
| | | </ul> |
| | | |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- tickets --> |
| | | <div class="span9"> |
| | | <div class="btn-toolbar" style="margin-top: 0px;"> |
| | | <div class="btn-group"> |
| | | <a class="btn dropdown-toggle" data-toggle="dropdown" href="#"><wicket:message key="gb.status"></wicket:message>: <span style="font-weight:bold;" wicket:id="selectedStatii"></span> <span class="caret"></span></a> |
| | | <ul class="dropdown-menu"> |
| | | <li><a wicket:id="openTickets"><wicket:message key="gb.open"></wicket:message></a></li> |
| | | <li><a wicket:id="closedTickets"><wicket:message key="gb.closed"></wicket:message></a></li> |
| | | <li><a wicket:id="allTickets"><wicket:message key="gb.all"></wicket:message></a></li> |
| | | <li class="divider"></li> |
| | | <li wicket:id="statii"><span wicket:id="statusLink"></span></li> |
| | | </ul> |
| | | </div> |
| | | <div class="btn-group"> |
| | | <a class="btn dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-sort"></i> <wicket:message key="gb.sort"></wicket:message>: <span style="font-weight:bold;" wicket:id="currentSort"></span> <span class="caret"></span></a> |
| | | <ul class="dropdown-menu"> |
| | | <li wicket:id="sort"><span wicket:id="sortLink"></span></li> |
| | | </ul> |
| | | </div> |
| | | |
| | | <div class="btn-group pull-right"> |
| | | <div class="pagination pagination-right pagination-small"> |
| | | <ul> |
| | | <li><a wicket:id="prevLink"><i class="fa fa-angle-double-left"></i></a></li> |
| | | <li wicket:id="pageLink"><span wicket:id="page"></span></li> |
| | | <li><a wicket:id="nextLink"><i class="fa fa-angle-double-right"></i></a></li> |
| | | </ul> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div wicket:id="ticketList"></div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | </wicket:extend> |
| | | </body> |
| | | </html> |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.wicket.pages; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | import org.apache.wicket.PageParameters; |
| | | import org.apache.wicket.markup.html.basic.Label; |
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink; |
| | | import org.apache.wicket.markup.repeater.Item; |
| | | import org.apache.wicket.markup.repeater.data.DataView; |
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider; |
| | | |
| | | import com.gitblit.Keys; |
| | | import com.gitblit.models.TicketModel; |
| | | import com.gitblit.models.TicketModel.Status; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.tickets.QueryBuilder; |
| | | import com.gitblit.tickets.QueryResult; |
| | | import com.gitblit.tickets.TicketIndexer.Lucene; |
| | | import com.gitblit.utils.ArrayUtils; |
| | | import com.gitblit.utils.StringUtils; |
| | | import com.gitblit.wicket.GitBlitWebSession; |
| | | import com.gitblit.wicket.TicketsUI; |
| | | import com.gitblit.wicket.TicketsUI.TicketSort; |
| | | import com.gitblit.wicket.WicketUtils; |
| | | import com.gitblit.wicket.panels.LinkPanel; |
| | | import com.gitblit.wicket.panels.TicketListPanel; |
| | | import com.gitblit.wicket.panels.TicketSearchForm; |
| | | import com.gitblit.wicket.panels.UserTitlePanel; |
| | | |
| | | /** |
| | | * My Tickets page |
| | | * |
| | | * @author Christian Buisson |
| | | * @author James Moger |
| | | */ |
| | | public class MyTicketsPage extends RootPage { |
| | | |
| | | public MyTicketsPage() { |
| | | this(null); |
| | | } |
| | | |
| | | public MyTicketsPage(PageParameters params) { |
| | | super(params); |
| | | setupPage("", getString("gb.myTickets")); |
| | | |
| | | UserModel currentUser = GitBlitWebSession.get().getUser(); |
| | | if (currentUser == null || UserModel.ANONYMOUS.equals(currentUser)) { |
| | | setRedirect(true); |
| | | setResponsePage(getApplication().getHomePage()); |
| | | return; |
| | | } |
| | | |
| | | final String username = currentUser.getName(); |
| | | final String[] statiiParam = (params == null) ? TicketsUI.openStatii : params.getStringArray(Lucene.status.name()); |
| | | final String assignedToParam = (params == null) ? "" : params.getString(Lucene.responsible.name(), null); |
| | | final String milestoneParam = (params == null) ? "" : params.getString(Lucene.milestone.name(), null); |
| | | final String queryParam = (params == null || StringUtils.isEmpty(params.getString("q", null))) ? "watchedby:" + username : params.getString("q", null); |
| | | final String searchParam = (params == null) ? "" : params.getString("s", null); |
| | | final String sortBy = (params == null) ? "" : Lucene.fromString(params.getString("sort", Lucene.created.name())).name(); |
| | | final boolean desc = (params == null) ? true : !"asc".equals(params.getString("direction", "desc")); |
| | | |
| | | // add the user title panel |
| | | add(new UserTitlePanel("userTitlePanel", currentUser, getString("gb.myTickets"))); |
| | | |
| | | // add search form |
| | | add(new TicketSearchForm("ticketSearchForm", null, searchParam, getClass(), params)); |
| | | |
| | | // standard queries |
| | | add(new BookmarkablePageLink<Void>("changesQuery", MyTicketsPage.class, |
| | | queryParameters( |
| | | Lucene.type.matches(TicketModel.Type.Proposal.name()), |
| | | milestoneParam, |
| | | statiiParam, |
| | | assignedToParam, |
| | | sortBy, |
| | | desc, |
| | | 1))); |
| | | |
| | | add(new BookmarkablePageLink<Void>("bugsQuery", MyTicketsPage.class, |
| | | queryParameters( |
| | | Lucene.type.matches(TicketModel.Type.Bug.name()), |
| | | milestoneParam, |
| | | statiiParam, |
| | | assignedToParam, |
| | | sortBy, |
| | | desc, |
| | | 1))); |
| | | |
| | | add(new BookmarkablePageLink<Void>("enhancementsQuery", MyTicketsPage.class, |
| | | queryParameters( |
| | | Lucene.type.matches(TicketModel.Type.Enhancement.name()), |
| | | milestoneParam, |
| | | statiiParam, |
| | | assignedToParam, |
| | | sortBy, |
| | | desc, |
| | | 1))); |
| | | |
| | | add(new BookmarkablePageLink<Void>("tasksQuery", MyTicketsPage.class, |
| | | queryParameters( |
| | | Lucene.type.matches(TicketModel.Type.Task.name()), |
| | | milestoneParam, |
| | | statiiParam, |
| | | assignedToParam, |
| | | sortBy, |
| | | desc, |
| | | 1))); |
| | | |
| | | add(new BookmarkablePageLink<Void>("questionsQuery", MyTicketsPage.class, |
| | | queryParameters( |
| | | Lucene.type.matches(TicketModel.Type.Question.name()), |
| | | milestoneParam, |
| | | statiiParam, |
| | | assignedToParam, |
| | | sortBy, |
| | | desc, |
| | | 1))); |
| | | |
| | | add(new BookmarkablePageLink<Void>("resetQuery", MyTicketsPage.class, |
| | | queryParameters( |
| | | null, |
| | | milestoneParam, |
| | | TicketsUI.openStatii, |
| | | null, |
| | | null, |
| | | true, |
| | | 1))); |
| | | |
| | | add(new Label("userDivider")); |
| | | add(new BookmarkablePageLink<Void>("createdQuery", MyTicketsPage.class, |
| | | queryParameters( |
| | | Lucene.createdby.matches(username), |
| | | milestoneParam, |
| | | statiiParam, |
| | | assignedToParam, |
| | | sortBy, |
| | | desc, |
| | | 1))); |
| | | |
| | | add(new BookmarkablePageLink<Void>("watchedQuery", MyTicketsPage.class, |
| | | queryParameters( |
| | | Lucene.watchedby.matches(username), |
| | | milestoneParam, |
| | | statiiParam, |
| | | assignedToParam, |
| | | sortBy, |
| | | desc, |
| | | 1))); |
| | | add(new BookmarkablePageLink<Void>("mentionsQuery", MyTicketsPage.class, |
| | | queryParameters( |
| | | Lucene.mentions.matches(username), |
| | | milestoneParam, |
| | | statiiParam, |
| | | assignedToParam, |
| | | sortBy, |
| | | desc, |
| | | 1))); |
| | | add(new BookmarkablePageLink<Void>("responsibleQuery", MyTicketsPage.class, |
| | | queryParameters( |
| | | Lucene.responsible.matches(username), |
| | | milestoneParam, |
| | | statiiParam, |
| | | assignedToParam, |
| | | sortBy, |
| | | desc, |
| | | 1))); |
| | | |
| | | // states |
| | | if (ArrayUtils.isEmpty(statiiParam)) { |
| | | add(new Label("selectedStatii", getString("gb.all"))); |
| | | } else { |
| | | add(new Label("selectedStatii", StringUtils.flattenStrings(Arrays.asList(statiiParam), ","))); |
| | | } |
| | | add(new BookmarkablePageLink<Void>("openTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, TicketsUI.openStatii, assignedToParam, sortBy, desc, 1))); |
| | | add(new BookmarkablePageLink<Void>("closedTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, TicketsUI.closedStatii, assignedToParam, sortBy, desc, 1))); |
| | | add(new BookmarkablePageLink<Void>("allTickets", MyTicketsPage.class, queryParameters(queryParam, milestoneParam, null, assignedToParam, sortBy, desc, 1))); |
| | | |
| | | // by status |
| | | List<Status> statii = new ArrayList<Status>(Arrays.asList(Status.values())); |
| | | statii.remove(Status.Closed); |
| | | ListDataProvider<Status> resolutionsDp = new ListDataProvider<Status>(statii); |
| | | DataView<Status> statiiLinks = new DataView<Status>("statii", resolutionsDp) { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void populateItem(final Item<Status> item) { |
| | | final Status status = item.getModelObject(); |
| | | PageParameters p = queryParameters(queryParam, milestoneParam, new String [] { status.name().toLowerCase() }, assignedToParam, sortBy, desc, 1); |
| | | String css = TicketsUI.getStatusClass(status); |
| | | item.add(new LinkPanel("statusLink", css, status.toString(), MyTicketsPage.class, p).setRenderBodyOnly(true)); |
| | | } |
| | | }; |
| | | add(statiiLinks); |
| | | |
| | | List<TicketSort> sortChoices = new ArrayList<TicketSort>(); |
| | | sortChoices.add(new TicketSort(getString("gb.sortNewest"), Lucene.created.name(), true)); |
| | | sortChoices.add(new TicketSort(getString("gb.sortOldest"), Lucene.created.name(), false)); |
| | | sortChoices.add(new TicketSort(getString("gb.sortMostRecentlyUpdated"), Lucene.updated.name(), true)); |
| | | sortChoices.add(new TicketSort(getString("gb.sortLeastRecentlyUpdated"), Lucene.updated.name(), false)); |
| | | sortChoices.add(new TicketSort(getString("gb.sortMostComments"), Lucene.comments.name(), true)); |
| | | sortChoices.add(new TicketSort(getString("gb.sortLeastComments"), Lucene.comments.name(), false)); |
| | | sortChoices.add(new TicketSort(getString("gb.sortMostPatchsetRevisions"), Lucene.patchsets.name(), true)); |
| | | sortChoices.add(new TicketSort(getString("gb.sortLeastPatchsetRevisions"), Lucene.patchsets.name(), false)); |
| | | sortChoices.add(new TicketSort(getString("gb.sortMostVotes"), Lucene.votes.name(), true)); |
| | | sortChoices.add(new TicketSort(getString("gb.sortLeastVotes"), Lucene.votes.name(), false)); |
| | | |
| | | TicketSort currentSort = sortChoices.get(0); |
| | | for (TicketSort ts : sortChoices) { |
| | | if (ts.sortBy.equals(sortBy) && desc == ts.desc) { |
| | | currentSort = ts; |
| | | break; |
| | | } |
| | | } |
| | | add(new Label("currentSort", currentSort.name)); |
| | | |
| | | ListDataProvider<TicketSort> sortChoicesDp = new ListDataProvider<TicketSort>(sortChoices); |
| | | DataView<TicketSort> sortMenu = new DataView<TicketSort>("sort", sortChoicesDp) { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void populateItem(final Item<TicketSort> item) { |
| | | final TicketSort ts = item.getModelObject(); |
| | | PageParameters params = queryParameters(queryParam, milestoneParam, statiiParam, assignedToParam, ts.sortBy, ts.desc, 1); |
| | | item.add(new LinkPanel("sortLink", null, ts.name, MyTicketsPage.class, params).setRenderBodyOnly(true)); |
| | | } |
| | | }; |
| | | add(sortMenu); |
| | | |
| | | // Build Query here |
| | | QueryBuilder qb = new QueryBuilder(queryParam); |
| | | if (!qb.containsField(Lucene.status.name()) && !ArrayUtils.isEmpty(statiiParam)) { |
| | | // specify the states |
| | | boolean not = false; |
| | | QueryBuilder q = new QueryBuilder(); |
| | | for (String state : statiiParam) { |
| | | if (state.charAt(0) == '!') { |
| | | not = true; |
| | | q.and(Lucene.status.doesNotMatch(state.substring(1))); |
| | | } else { |
| | | q.or(Lucene.status.matches(state)); |
| | | } |
| | | } |
| | | if (not) { |
| | | qb.and(q.toString()); |
| | | } else { |
| | | qb.and(q.toSubquery().toString()); |
| | | } |
| | | } |
| | | |
| | | final String luceneQuery; |
| | | if (qb.containsField(Lucene.createdby.name()) |
| | | || qb.containsField(Lucene.responsible.name()) |
| | | || qb.containsField(Lucene.watchedby.name())) { |
| | | // focused "my tickets" query |
| | | luceneQuery = qb.build(); |
| | | } else { |
| | | // general "my tickets" query |
| | | QueryBuilder myQuery = new QueryBuilder(); |
| | | myQuery.or(Lucene.createdby.matches(username)); |
| | | myQuery.or(Lucene.responsible.matches(username)); |
| | | myQuery.or(Lucene.watchedby.matches(username)); |
| | | myQuery.and(qb.toSubquery().toString()); |
| | | luceneQuery = myQuery.build(); |
| | | } |
| | | |
| | | // paging links |
| | | int page = (params != null) ? Math.max(1, WicketUtils.getPage(params)) : 1; |
| | | int pageSize = app().settings().getInteger(Keys.tickets.perPage, 25); |
| | | |
| | | List<QueryResult> results; |
| | | if(StringUtils.isEmpty(searchParam)) { |
| | | results = app().tickets().queryFor(luceneQuery, page, pageSize, sortBy, desc); |
| | | } else { |
| | | results = app().tickets().searchFor(null, searchParam, page, pageSize); |
| | | } |
| | | |
| | | int totalResults = results.size() == 0 ? 0 : results.get(0).totalResults; |
| | | buildPager(queryParam, milestoneParam, statiiParam, assignedToParam, sortBy, desc, page, pageSize, results.size(), totalResults); |
| | | |
| | | final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true); |
| | | add(new TicketListPanel("ticketList", results, showSwatch, true)); |
| | | } |
| | | |
| | | protected PageParameters queryParameters( |
| | | String query, |
| | | String milestone, |
| | | String[] states, |
| | | String assignedTo, |
| | | String sort, |
| | | boolean descending, |
| | | int page) { |
| | | |
| | | PageParameters params = WicketUtils.newRepositoryParameter(""); |
| | | if (!StringUtils.isEmpty(query)) { |
| | | params.add("q", query); |
| | | } |
| | | if (!StringUtils.isEmpty(milestone)) { |
| | | params.add(Lucene.milestone.name(), milestone); |
| | | } |
| | | if (!ArrayUtils.isEmpty(states)) { |
| | | for (String state : states) { |
| | | params.add(Lucene.status.name(), state); |
| | | } |
| | | } |
| | | if (!StringUtils.isEmpty(assignedTo)) { |
| | | params.add(Lucene.responsible.name(), assignedTo); |
| | | } |
| | | if (!StringUtils.isEmpty(sort)) { |
| | | params.add("sort", sort); |
| | | } |
| | | if (!descending) { |
| | | params.add("direction", "asc"); |
| | | } |
| | | if (page > 1) { |
| | | params.add("pg", "" + page); |
| | | } |
| | | return params; |
| | | } |
| | | |
| | | protected void buildPager( |
| | | final String query, |
| | | final String milestone, |
| | | final String [] states, |
| | | final String assignedTo, |
| | | final String sort, |
| | | final boolean desc, |
| | | final int page, |
| | | int pageSize, |
| | | int count, |
| | | int total) { |
| | | |
| | | boolean showNav = total > (2 * pageSize); |
| | | boolean allowPrev = page > 1; |
| | | boolean allowNext = (pageSize * (page - 1) + count) < total; |
| | | add(new BookmarkablePageLink<Void>("prevLink", MyTicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, page - 1)).setEnabled(allowPrev).setVisible(showNav)); |
| | | add(new BookmarkablePageLink<Void>("nextLink", MyTicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, page + 1)).setEnabled(allowNext).setVisible(showNav)); |
| | | |
| | | if (total <= pageSize) { |
| | | add(new Label("pageLink").setVisible(false)); |
| | | return; |
| | | } |
| | | |
| | | // determine page numbers to display |
| | | int pages = count == 0 ? 0 : ((total / pageSize) + (total % pageSize == 0 ? 0 : 1)); |
| | | // preferred number of pagelinks |
| | | int segments = 5; |
| | | if (pages < segments) { |
| | | // not enough data for preferred number of page links |
| | | segments = pages; |
| | | } |
| | | int minpage = Math.min(Math.max(1, page - 2), pages - (segments - 1)); |
| | | int maxpage = Math.min(pages, minpage + (segments - 1)); |
| | | List<Integer> sequence = new ArrayList<Integer>(); |
| | | for (int i = minpage; i <= maxpage; i++) { |
| | | sequence.add(i); |
| | | } |
| | | |
| | | ListDataProvider<Integer> pagesDp = new ListDataProvider<Integer>(sequence); |
| | | DataView<Integer> pagesView = new DataView<Integer>("pageLink", pagesDp) { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void populateItem(final Item<Integer> item) { |
| | | final Integer i = item.getModelObject(); |
| | | LinkPanel link = new LinkPanel("page", null, "" + i, MyTicketsPage.class, queryParameters(query, milestone, states, assignedTo, sort, desc, i)); |
| | | link.setRenderBodyOnly(true); |
| | | if (i == page) { |
| | | WicketUtils.setCssClass(item, "active"); |
| | | } |
| | | item.add(link); |
| | | } |
| | | }; |
| | | add(pagesView); |
| | | } |
| | | } |
New file |
| | |
| | | <!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"> |
| | |
|
| | | <wicket:extend>
|
| | | <body onload="document.getElementById('name').focus();">
|
| | | |
| | | <div class="container">
|
| | | <!-- page header -->
|
| | | <div class="title" style="font-size: 22px; color: rgb(0, 32, 96);padding: 3px 0px 7px;">
|
| | | <span class="project"><wicket:message key="gb.newMilestone"></wicket:message></span>
|
| | | </div>
|
| | |
|
| | | <form style="padding-top:5px;" wicket:id="editForm">
|
| | | <div class="row">
|
| | | <div class="span12">
|
| | | <!-- New Milestone Table -->
|
| | | <table class="ticket">
|
| | | <tr><th><wicket:message key="gb.milestone"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="name" id="name"></input></td></tr>
|
| | | <tr><th><wicket:message key="gb.due"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="due"></input> <span class="help-inline" wicket:id="dueFormat"></span></td></tr>
|
| | | </table>
|
| | | </div>
|
| | | </div> |
| | |
|
| | | <div class="row">
|
| | | <div class="span12">
|
| | | <div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Create" wicket:message="value:gb.create" wicket:id="create" /> <input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" /></div>
|
| | | </div>
|
| | | </div>
|
| | | </form>
|
| | | </div>
|
| | | </body>
|
| | |
|
| | | </wicket:extend>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.pages;
|
| | |
|
| | | import java.util.Date;
|
| | |
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.RestartResponseException;
|
| | | import org.apache.wicket.ajax.AjaxRequestTarget;
|
| | | import org.apache.wicket.ajax.markup.html.form.AjaxButton;
|
| | | import org.apache.wicket.extensions.markup.html.form.DateTextField;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.Button;
|
| | | import org.apache.wicket.markup.html.form.Form;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | |
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.tickets.TicketMilestone;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.utils.TimeUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | |
|
| | | /**
|
| | | * Page for creating a new milestone.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class NewMilestonePage extends RepositoryPage {
|
| | |
|
| | | private IModel<String> nameModel;
|
| | |
|
| | | private IModel<Date> dueModel;
|
| | |
|
| | | public NewMilestonePage(PageParameters params) {
|
| | | super(params);
|
| | |
|
| | | RepositoryModel model = getRepositoryModel();
|
| | | if (!app().tickets().isAcceptingTicketUpdates(model)) {
|
| | | // ticket service is read-only
|
| | | throw new RestartResponseException(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | }
|
| | |
|
| | | UserModel currentUser = GitBlitWebSession.get().getUser();
|
| | | if (currentUser == null) {
|
| | | currentUser = UserModel.ANONYMOUS;
|
| | | }
|
| | |
|
| | | if (!currentUser.isAuthenticated || !currentUser.canAdmin(model)) {
|
| | | // administration prohibited
|
| | | throw new RestartResponseException(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | }
|
| | |
|
| | | setStatelessHint(false);
|
| | | setOutputMarkupId(true);
|
| | |
|
| | | Form<Void> form = new Form<Void>("editForm");
|
| | | add(form);
|
| | |
|
| | | nameModel = Model.of("");
|
| | | dueModel = Model.of(new Date(System.currentTimeMillis() + TimeUtils.ONEDAY));
|
| | |
|
| | | form.add(new TextField<String>("name", nameModel));
|
| | | form.add(new DateTextField("due", dueModel, "yyyy-MM-dd"));
|
| | | form.add(new Label("dueFormat", "yyyy-MM-dd"));
|
| | |
|
| | | form.add(new AjaxButton("create") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
|
| | | String name = nameModel.getObject();
|
| | | if (StringUtils.isEmpty(name)) {
|
| | | // invalid name
|
| | | return;
|
| | | }
|
| | |
|
| | | TicketMilestone milestone = app().tickets().getMilestone(getRepositoryModel(), name);
|
| | | if (milestone != null) {
|
| | | // milestone already exists
|
| | | return;
|
| | | }
|
| | |
|
| | | Date due = dueModel.getObject();
|
| | |
|
| | | UserModel currentUser = GitBlitWebSession.get().getUser();
|
| | | String createdBy = currentUser.username;
|
| | |
|
| | | milestone = app().tickets().createMilestone(getRepositoryModel(), name, createdBy);
|
| | | if (milestone != null) {
|
| | | milestone.due = due;
|
| | | app().tickets().updateMilestone(getRepositoryModel(), milestone, createdBy);
|
| | | throw new RestartResponseException(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | } else {
|
| | | // TODO error
|
| | | }
|
| | | }
|
| | | });
|
| | |
|
| | | Button cancel = new Button("cancel") {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void onSubmit() {
|
| | | setResponsePage(TicketsPage.class, WicketUtils.newOpenTicketsParameter(repositoryName));
|
| | | }
|
| | | };
|
| | | cancel.setDefaultFormProcessing(false);
|
| | | form.add(cancel);
|
| | |
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected String getPageName() {
|
| | | return getString("gb.newMilestone");
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected Class<? extends BasePage> getRepoNavPageClass() {
|
| | | return TicketsPage.class;
|
| | | }
|
| | | }
|
New file |
| | |
| | | <!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"> |
| | |
|
| | | <wicket:extend>
|
| | | <body onload="document.getElementById('name').focus();">
|
| | | <form style="padding-top:5px;" wicket:id="editForm">
|
| | | <div class="row">
|
| | | <div class="span12">
|
| | |
|
| | | <div wicket:id="namePanel"></div>
|
| | | |
| | | <hr/>
|
| | | |
| | | <div wicket:id="accessPolicyPanel"></div>
|
| | | |
| | | <hr/>
|
| | | |
| | | <h4><wicket:message key="gb.initialCommit"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.initialCommitDescription"></wicket:message></p>
|
| | | |
| | | <div wicket:id="addReadme"></div>
|
| | | |
| | | <div wicket:id="addGitIgnore"></div>
|
| | | |
| | | <div wicket:id="addGitFlow"></div>
|
| | | </div>
|
| | | </div>
|
| | |
|
| | | <div class="row">
|
| | | <div class="span12">
|
| | | <div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Create" wicket:message="value:gb.create" wicket:id="create" /></div>
|
| | | </div>
|
| | | </div>
|
| | |
|
| | | </form> |
| | | </body>
|
| | | </wicket:extend>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.pages;
|
| | |
|
| | | import java.io.File;
|
| | | import java.io.IOException;
|
| | | import java.io.UnsupportedEncodingException;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Collections;
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.behavior.SimpleAttributeModifier;
|
| | | import org.apache.wicket.markup.html.form.Button;
|
| | | import org.apache.wicket.markup.html.form.Form;
|
| | | import org.apache.wicket.model.CompoundPropertyModel;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | | import org.eclipse.jgit.dircache.DirCache;
|
| | | import org.eclipse.jgit.dircache.DirCacheBuilder;
|
| | | import org.eclipse.jgit.dircache.DirCacheEntry;
|
| | | import org.eclipse.jgit.lib.CommitBuilder;
|
| | | import org.eclipse.jgit.lib.Config;
|
| | | import org.eclipse.jgit.lib.FileMode;
|
| | | import org.eclipse.jgit.lib.ObjectId;
|
| | | import org.eclipse.jgit.lib.ObjectInserter;
|
| | | import org.eclipse.jgit.lib.PersonIdent;
|
| | | import org.eclipse.jgit.lib.RefUpdate;
|
| | | import org.eclipse.jgit.lib.RefUpdate.Result;
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | | import org.eclipse.jgit.revwalk.RevWalk;
|
| | |
|
| | | import com.gitblit.Constants;
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.Constants.AuthorizationControl;
|
| | | import com.gitblit.GitBlitException;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.ArrayUtils;
|
| | | import com.gitblit.utils.FileUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.AccessPolicyPanel;
|
| | | import com.gitblit.wicket.panels.BooleanChoiceOption;
|
| | | import com.gitblit.wicket.panels.BooleanOption;
|
| | | import com.gitblit.wicket.panels.RepositoryNamePanel;
|
| | |
|
| | | public class NewRepositoryPage extends RootSubPage {
|
| | |
|
| | | private final RepositoryModel repositoryModel;
|
| | | private IModel<Boolean> addReadmeModel;
|
| | | private Model<String> gitignoreModel;
|
| | | private IModel<Boolean> addGitflowModel;
|
| | | private IModel<Boolean> addGitignoreModel;
|
| | | private AccessPolicyPanel accessPolicyPanel;
|
| | | private RepositoryNamePanel namePanel;
|
| | |
|
| | | public NewRepositoryPage() {
|
| | | // create constructor
|
| | | super();
|
| | | repositoryModel = new RepositoryModel();
|
| | |
|
| | | setupPage(getString("gb.newRepository"), "");
|
| | |
|
| | | setStatelessHint(false);
|
| | | setOutputMarkupId(true);
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected boolean requiresPageMap() {
|
| | | return true;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected Class<? extends BasePage> getRootNavPageClass() {
|
| | | return RepositoriesPage.class;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void onInitialize() {
|
| | | super.onInitialize();
|
| | |
|
| | | CompoundPropertyModel<RepositoryModel> rModel = new CompoundPropertyModel<>(repositoryModel);
|
| | | Form<RepositoryModel> form = new Form<RepositoryModel>("editForm", rModel) {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | protected void onSubmit() {
|
| | | try {
|
| | | if (!namePanel.updateModel(repositoryModel)) {
|
| | | return;
|
| | | }
|
| | | accessPolicyPanel.updateModel(repositoryModel);
|
| | |
|
| | | repositoryModel.owners = new ArrayList<String>();
|
| | | repositoryModel.owners.add(GitBlitWebSession.get().getUsername());
|
| | |
|
| | | // setup branch defaults
|
| | | boolean useGitFlow = addGitflowModel.getObject();
|
| | |
|
| | | repositoryModel.HEAD = Constants.R_MASTER;
|
| | | repositoryModel.mergeTo = Constants.MASTER;
|
| | | if (useGitFlow) {
|
| | | // tickets normally merge to develop unless they are hotfixes
|
| | | repositoryModel.mergeTo = Constants.DEVELOP;
|
| | | }
|
| | |
|
| | | repositoryModel.allowForks = app().settings().getBoolean(Keys.web.allowForking, true);
|
| | |
|
| | | // optionally generate an initial commit
|
| | | boolean addReadme = addReadmeModel.getObject();
|
| | | String gitignore = null;
|
| | | boolean addGitignore = addGitignoreModel.getObject();
|
| | | if (addGitignore) {
|
| | | gitignore = gitignoreModel.getObject();
|
| | | if (StringUtils.isEmpty(gitignore)) {
|
| | | throw new GitBlitException(getString("gb.pleaseSelectGitIgnore"));
|
| | | }
|
| | | }
|
| | |
|
| | | // init the repository
|
| | | app().gitblit().updateRepositoryModel(repositoryModel.name, repositoryModel, true);
|
| | |
|
| | | // optionally create an initial commit
|
| | | initialCommit(repositoryModel, addReadme, gitignore, useGitFlow);
|
| | |
|
| | | } catch (GitBlitException e) {
|
| | | error(e.getMessage());
|
| | | return;
|
| | | }
|
| | | setRedirect(true);
|
| | | setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name));
|
| | | }
|
| | | };
|
| | |
|
| | | // do not let the browser pre-populate these fields
|
| | | form.add(new SimpleAttributeModifier("autocomplete", "off"));
|
| | |
|
| | | namePanel = new RepositoryNamePanel("namePanel", repositoryModel);
|
| | | form.add(namePanel);
|
| | |
|
| | | // prepare the default access controls
|
| | | AccessRestrictionType defaultRestriction = AccessRestrictionType.fromName(
|
| | | app().settings().getString(Keys.git.defaultAccessRestriction, AccessRestrictionType.PUSH.name()));
|
| | | if (AccessRestrictionType.NONE == defaultRestriction) {
|
| | | defaultRestriction = AccessRestrictionType.PUSH;
|
| | | }
|
| | | AuthorizationControl defaultControl = AuthorizationControl.fromName(
|
| | | app().settings().getString(Keys.git.defaultAuthorizationControl, AuthorizationControl.NAMED.name()));
|
| | |
|
| | | if (AuthorizationControl.AUTHENTICATED == defaultControl) {
|
| | | defaultRestriction = AccessRestrictionType.PUSH;
|
| | | }
|
| | |
|
| | | repositoryModel.authorizationControl = defaultControl;
|
| | | repositoryModel.accessRestriction = defaultRestriction;
|
| | |
|
| | | accessPolicyPanel = new AccessPolicyPanel("accessPolicyPanel", repositoryModel);
|
| | | form.add(accessPolicyPanel);
|
| | |
|
| | | //
|
| | | // initial commit options
|
| | | //
|
| | |
|
| | | // add README
|
| | | addReadmeModel = Model.of(false);
|
| | | form.add(new BooleanOption("addReadme",
|
| | | getString("gb.initWithReadme"),
|
| | | getString("gb.initWithReadmeDescription"),
|
| | | addReadmeModel));
|
| | |
|
| | | // add .gitignore
|
| | | File gitignoreDir = app().runtime().getFileOrFolder(Keys.git.gitignoreFolder, "${baseFolder}/gitignore");
|
| | | File [] files = gitignoreDir.listFiles();
|
| | | if (files == null) {
|
| | | files = new File[0];
|
| | | }
|
| | | List<String> gitignores = new ArrayList<String>();
|
| | | for (File file : files) {
|
| | | if (file.isFile() && file.getName().endsWith(".gitignore")) {
|
| | | gitignores.add(StringUtils.stripFileExtension(file.getName()));
|
| | | }
|
| | | }
|
| | | Collections.sort(gitignores);
|
| | |
|
| | | gitignoreModel = Model.of("");
|
| | | addGitignoreModel = Model.of(false);
|
| | | form.add(new BooleanChoiceOption<String>("addGitIgnore",
|
| | | getString("gb.initWithGitignore"),
|
| | | getString("gb.initWithGitignoreDescription"),
|
| | | addGitignoreModel,
|
| | | gitignoreModel,
|
| | | gitignores).setVisible(gitignores.size() > 0));
|
| | |
|
| | | // TODO consider gitflow at creation (ticket-55)
|
| | | addGitflowModel = Model.of(false);
|
| | | form.add(new BooleanOption("addGitFlow",
|
| | | "Include a .gitflow file",
|
| | | "This will generate a config file which guides Git clients in setting up Gitflow branches.",
|
| | | addGitflowModel).setVisible(false));
|
| | |
|
| | | form.add(new Button("create"));
|
| | |
|
| | | add(form);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Prepare the initial commit for the repository.
|
| | | *
|
| | | * @param repository
|
| | | * @param addReadme
|
| | | * @param gitignore
|
| | | * @param addGitFlow
|
| | | * @return true if an initial commit was created
|
| | | */
|
| | | protected boolean initialCommit(RepositoryModel repository, boolean addReadme, String gitignore,
|
| | | boolean addGitFlow) {
|
| | | boolean initialCommit = addReadme || !StringUtils.isEmpty(gitignore) || addGitFlow;
|
| | | if (!initialCommit) {
|
| | | return false;
|
| | | }
|
| | |
|
| | | // build an initial commit
|
| | | boolean success = false;
|
| | | Repository db = app().repositories().getRepository(repositoryModel.name);
|
| | | ObjectInserter odi = db.newObjectInserter();
|
| | | try {
|
| | |
|
| | | UserModel user = GitBlitWebSession.get().getUser();
|
| | | PersonIdent author = new PersonIdent(user.getDisplayName(), user.emailAddress);
|
| | |
|
| | | DirCache newIndex = DirCache.newInCore();
|
| | | DirCacheBuilder indexBuilder = newIndex.builder();
|
| | |
|
| | | if (addReadme) {
|
| | | // insert a README
|
| | | String title = StringUtils.stripDotGit(StringUtils.getLastPathElement(repositoryModel.name));
|
| | | String description = repositoryModel.description == null ? "" : repositoryModel.description;
|
| | | String readme = String.format("## %s\n\n%s\n\n", title, description);
|
| | | byte [] bytes = readme.getBytes(Constants.ENCODING);
|
| | |
|
| | | DirCacheEntry entry = new DirCacheEntry("README.md");
|
| | | entry.setLength(bytes.length);
|
| | | entry.setLastModified(System.currentTimeMillis());
|
| | | entry.setFileMode(FileMode.REGULAR_FILE);
|
| | | entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes));
|
| | |
|
| | | indexBuilder.add(entry);
|
| | | }
|
| | |
|
| | | if (!StringUtils.isEmpty(gitignore)) {
|
| | | // insert a .gitignore file
|
| | | File dir = app().runtime().getFileOrFolder(Keys.git.gitignoreFolder, "${baseFolder}/gitignore");
|
| | | File file = new File(dir, gitignore + ".gitignore");
|
| | | if (file.exists() && file.length() > 0) {
|
| | | byte [] bytes = FileUtils.readContent(file);
|
| | | if (!ArrayUtils.isEmpty(bytes)) {
|
| | | DirCacheEntry entry = new DirCacheEntry(".gitignore");
|
| | | entry.setLength(bytes.length);
|
| | | entry.setLastModified(System.currentTimeMillis());
|
| | | entry.setFileMode(FileMode.REGULAR_FILE);
|
| | | entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes));
|
| | |
|
| | | indexBuilder.add(entry);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (addGitFlow) {
|
| | | // insert a .gitflow file
|
| | | Config config = new Config();
|
| | | config.setString("gitflow", null, "masterBranch", Constants.MASTER);
|
| | | config.setString("gitflow", null, "developBranch", Constants.DEVELOP);
|
| | | config.setString("gitflow", null, "featureBranchPrefix", "feature/");
|
| | | config.setString("gitflow", null, "releaseBranchPrefix", "release/");
|
| | | config.setString("gitflow", null, "hotfixBranchPrefix", "hotfix/");
|
| | | config.setString("gitflow", null, "supportBranchPrefix", "support/");
|
| | | config.setString("gitflow", null, "versionTagPrefix", "");
|
| | |
|
| | | byte [] bytes = config.toText().getBytes(Constants.ENCODING);
|
| | |
|
| | | DirCacheEntry entry = new DirCacheEntry(".gitflow");
|
| | | entry.setLength(bytes.length);
|
| | | entry.setLastModified(System.currentTimeMillis());
|
| | | entry.setFileMode(FileMode.REGULAR_FILE);
|
| | | entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes));
|
| | |
|
| | | indexBuilder.add(entry);
|
| | | }
|
| | |
|
| | | indexBuilder.finish();
|
| | |
|
| | | if (newIndex.getEntryCount() == 0) {
|
| | | // nothing to commit
|
| | | return false;
|
| | | }
|
| | |
|
| | | ObjectId treeId = newIndex.writeTree(odi);
|
| | |
|
| | | // Create a commit object
|
| | | CommitBuilder commit = new CommitBuilder();
|
| | | commit.setAuthor(author);
|
| | | commit.setCommitter(author);
|
| | | commit.setEncoding(Constants.ENCODING);
|
| | | commit.setMessage("Initial commit");
|
| | | commit.setTreeId(treeId);
|
| | |
|
| | | // Insert the commit into the repository
|
| | | ObjectId commitId = odi.insert(commit);
|
| | | odi.flush();
|
| | |
|
| | | // set the branch refs
|
| | | RevWalk revWalk = new RevWalk(db);
|
| | | try {
|
| | | // set the master branch
|
| | | RevCommit revCommit = revWalk.parseCommit(commitId);
|
| | | RefUpdate masterRef = db.updateRef(Constants.R_MASTER);
|
| | | masterRef.setNewObjectId(commitId);
|
| | | masterRef.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
|
| | | Result masterRC = masterRef.update();
|
| | | switch (masterRC) {
|
| | | case NEW:
|
| | | success = true;
|
| | | break;
|
| | | default:
|
| | | success = false;
|
| | | }
|
| | |
|
| | | if (addGitFlow) {
|
| | | // set the develop branch for git-flow
|
| | | RefUpdate developRef = db.updateRef(Constants.R_DEVELOP);
|
| | | developRef.setNewObjectId(commitId);
|
| | | developRef.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
|
| | | Result developRC = developRef.update();
|
| | | switch (developRC) {
|
| | | case NEW:
|
| | | success = true;
|
| | | break;
|
| | | default:
|
| | | success = false;
|
| | | }
|
| | | }
|
| | | } finally {
|
| | | revWalk.release();
|
| | | }
|
| | | } catch (UnsupportedEncodingException e) {
|
| | | logger().error(null, e);
|
| | | } catch (IOException e) {
|
| | | logger().error(null, e);
|
| | | } finally {
|
| | | odi.release();
|
| | | db.close();
|
| | | }
|
| | | return success;
|
| | | }
|
| | | }
|
| | |
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | |
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.Menu.MenuDivider;
|
| | | import com.gitblit.models.Menu.MenuItem;
|
| | | import com.gitblit.models.Menu.ParameterMenuItem;
|
| | | import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
|
| | | import com.gitblit.models.NavLink;
|
| | | import com.gitblit.models.ProjectModel;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | |
| | | import com.gitblit.wicket.GitBlitWebApp;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.GitblitRedirectException;
|
| | | import com.gitblit.wicket.PageRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.FilterableRepositoryList;
|
| | |
|
| | |
| | | }
|
| | |
|
| | | @Override
|
| | | protected void addDropDownMenus(List<PageRegistration> pages) {
|
| | | protected void addDropDownMenus(List<NavLink> navLinks) {
|
| | | PageParameters params = getPageParameters();
|
| | |
|
| | | DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",
|
| | | DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",
|
| | | ProjectPage.class);
|
| | | // preserve time filter option on repository choices
|
| | | menu.menuItems.addAll(getRepositoryFilterItems(params));
|
| | |
| | |
|
| | | if (menu.menuItems.size() > 0) {
|
| | | // Reset Filter
|
| | | menu.menuItems.add(new DropDownMenuItem(getString("gb.reset"), "p", WicketUtils.getProjectName(params)));
|
| | | menu.menuItems.add(new ParameterMenuItem(getString("gb.reset"), "p", WicketUtils.getProjectName(params)));
|
| | | }
|
| | |
|
| | | pages.add(menu);
|
| | | navLinks.add(menu);
|
| | |
|
| | | DropDownMenuRegistration projects = new DropDownMenuRegistration("gb.projects",
|
| | | DropDownPageMenuNavLink projects = new DropDownPageMenuNavLink("gb.projects",
|
| | | ProjectPage.class);
|
| | | projects.menuItems.addAll(getProjectsMenu());
|
| | | pages.add(projects);
|
| | | navLinks.add(projects);
|
| | | }
|
| | |
|
| | | @Override
|
| | |
| | | return null;
|
| | | }
|
| | |
|
| | | protected List<DropDownMenuItem> getProjectsMenu() {
|
| | | List<DropDownMenuItem> menu = new ArrayList<DropDownMenuItem>();
|
| | | protected List<MenuItem> getProjectsMenu() {
|
| | | List<MenuItem> menu = new ArrayList<MenuItem>();
|
| | | List<ProjectModel> projects = new ArrayList<ProjectModel>();
|
| | | for (ProjectModel model : getProjectModels()) {
|
| | | if (!model.isUserProject()) {
|
| | |
| | | }
|
| | |
|
| | | for (ProjectModel project : projects) {
|
| | | menu.add(new DropDownMenuItem(project.getDisplayName(), "p", project.name));
|
| | | menu.add(new ParameterMenuItem(project.getDisplayName(), "p", project.name));
|
| | | }
|
| | | if (showAllProjects) {
|
| | | menu.add(new DropDownMenuItem());
|
| | | menu.add(new DropDownMenuItem("all projects", null, null));
|
| | | menu.add(new MenuDivider());
|
| | | menu.add(new ParameterMenuItem("all projects"));
|
| | | }
|
| | | return menu;
|
| | | }
|
| | |
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
| | |
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.Menu.ParameterMenuItem;
|
| | | import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
|
| | | import com.gitblit.models.NavLink;
|
| | | import com.gitblit.models.ProjectModel;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.PageRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.LinkPanel;
|
| | |
|
| | |
| | | }
|
| | |
|
| | | @Override
|
| | | protected void addDropDownMenus(List<PageRegistration> pages) {
|
| | | protected void addDropDownMenus(List<NavLink> navLinks) {
|
| | | PageParameters params = getPageParameters();
|
| | |
|
| | | DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",
|
| | | DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",
|
| | | ProjectsPage.class);
|
| | | // preserve time filter option on repository choices
|
| | | menu.menuItems.addAll(getRepositoryFilterItems(params));
|
| | |
| | |
|
| | | if (menu.menuItems.size() > 0) {
|
| | | // Reset Filter
|
| | | menu.menuItems.add(new DropDownMenuItem(getString("gb.reset"), null, null));
|
| | | menu.menuItems.add(new ParameterMenuItem(getString("gb.reset")));
|
| | | }
|
| | |
|
| | | pages.add(menu);
|
| | | navLinks.add(menu);
|
| | | }
|
| | | }
|
| | |
| | | import java.io.InputStreamReader;
|
| | | import java.text.MessageFormat;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Iterator;
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.Component;
|
| | |
| | | import org.eclipse.jgit.lib.Constants;
|
| | |
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.Menu.ParameterMenuItem;
|
| | | import com.gitblit.models.NavLink;
|
| | | import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.utils.MarkdownUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.CacheControl;
|
| | | import com.gitblit.wicket.CacheControl.LastModified;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.PageRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.RepositoriesPanel;
|
| | |
|
| | |
| | | .setEscapeModelStrings(false).setVisible(message.length() > 0);
|
| | | add(repositoriesMessage);
|
| | |
|
| | | // conditionally include personal repositories in this page
|
| | | List<RepositoryModel> repositories = getRepositories(params);
|
| | | if (!app().settings().getBoolean(Keys.web.includePersonalRepositories, true)) {
|
| | | Iterator<RepositoryModel> itr = repositories.iterator();
|
| | | while (itr.hasNext()) {
|
| | | RepositoryModel rm = itr.next();
|
| | | if (rm.isPersonalRepository()) {
|
| | | itr.remove();
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | RepositoriesPanel repositoriesPanel = new RepositoriesPanel("repositoriesPanel", showAdmin,
|
| | | true, repositories, true, getAccessRestrictions());
|
| | |
| | | }
|
| | |
|
| | | @Override
|
| | | protected void addDropDownMenus(List<PageRegistration> pages) {
|
| | | protected void addDropDownMenus(List<NavLink> navLinks) {
|
| | | PageParameters params = getPageParameters();
|
| | |
|
| | | DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",
|
| | | DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",
|
| | | RepositoriesPage.class);
|
| | | // preserve time filter option on repository choices
|
| | | menu.menuItems.addAll(getRepositoryFilterItems(params));
|
| | |
| | |
|
| | | if (menu.menuItems.size() > 0) {
|
| | | // Reset Filter
|
| | | menu.menuItems.add(new DropDownMenuItem(getString("gb.reset"), null, null));
|
| | | menu.menuItems.add(new ParameterMenuItem(getString("gb.reset")));
|
| | | }
|
| | |
|
| | | pages.add(menu);
|
| | | navLinks.add(menu);
|
| | | }
|
| | |
|
| | | private String readMarkdown(String messageSource, String resource) {
|
| | |
| | | <form class="form-search" style="margin: 0px;" wicket:id="searchForm">
|
| | | <div class="input-append">
|
| | | <select class="span2" style="border-radius: 4px;" wicket:id="searchType"/>
|
| | | <input type="text" class="search-query" style="width: 170px;border-radius: 14px 0 0 14px; padding-left: 14px;" id="searchBox" wicket:id="searchBox" value=""/>
|
| | | <input type="text" class="input-medium search-query" style="border-radius: 14px 0 0 14px; padding-left: 14px;" id="searchBox" wicket:id="searchBox" value=""/>
|
| | | <button class="btn" style="border-radius: 0 14px 14px 0px;margin-left:-5px;" type="submit"><i class="icon-search"></i></button>
|
| | | </div>
|
| | | </form>
|
| | |
| | | import java.util.Arrays;
|
| | | import java.util.Date;
|
| | | import java.util.HashMap;
|
| | | import java.util.LinkedHashMap;
|
| | | import java.util.LinkedHashSet;
|
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | |
| | | import com.gitblit.Constants;
|
| | | import com.gitblit.GitBlitException;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.extensions.RepositoryNavLinkExtension;
|
| | | import com.gitblit.models.NavLink;
|
| | | import com.gitblit.models.NavLink.ExternalNavLink;
|
| | | import com.gitblit.models.NavLink.PageNavLink;
|
| | | import com.gitblit.models.ProjectModel;
|
| | | import com.gitblit.models.RefModel;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | |
| | | import com.gitblit.models.UserRepositoryPreferences;
|
| | | import com.gitblit.servlet.PagesServlet;
|
| | | import com.gitblit.servlet.SyndicationServlet;
|
| | | import com.gitblit.tickets.TicketIndexer.Lucene;
|
| | | import com.gitblit.utils.ArrayUtils;
|
| | | import com.gitblit.utils.BugtraqProcessor;
|
| | | import com.gitblit.utils.DeepCopier;
|
| | |
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.CacheControl;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.PageRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.OtherPageLink;
|
| | | import com.gitblit.wicket.SessionlessForm;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.LinkPanel;
|
| | |
| | |
|
| | | private Map<String, SubmoduleModel> submodules;
|
| | |
|
| | | private final Map<String, PageRegistration> registeredPages;
|
| | | private boolean showAdmin;
|
| | | private boolean isOwner;
|
| | |
|
| | |
| | | error(MessageFormat.format(getString("gb.repositoryNotSpecifiedFor"), getPageName()), true);
|
| | | }
|
| | |
|
| | | if (!getRepositoryModel().hasCommits) {
|
| | | if (!getRepositoryModel().hasCommits && getClass() != EmptyRepositoryPage.class) {
|
| | | throw new RestartResponseException(EmptyRepositoryPage.class, params);
|
| | | }
|
| | |
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | // register the available page links for this page and user
|
| | | registeredPages = registerPages();
|
| | | showAdmin = false;
|
| | | if (app().settings().getBoolean(Keys.web.authenticateAdminPages, true)) {
|
| | | boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, false);
|
| | | showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin();
|
| | | } else {
|
| | | showAdmin = app().settings().getBoolean(Keys.web.allowAdministration, false);
|
| | | }
|
| | | isOwner = GitBlitWebSession.get().isLoggedIn()
|
| | | && (getRepositoryModel().isOwner(GitBlitWebSession.get().getUsername()));
|
| | |
|
| | | // standard page links
|
| | | List<PageRegistration> pages = new ArrayList<PageRegistration>(registeredPages.values());
|
| | | NavigationPanel navigationPanel = new NavigationPanel("repositoryNavPanel", getRepoNavPageClass(), pages);
|
| | | // register the available navigation links for this page and user
|
| | | List<NavLink> navLinks = registerNavLinks();
|
| | |
|
| | | // standard navigation links
|
| | | NavigationPanel navigationPanel = new NavigationPanel("repositoryNavPanel", getRepoNavPageClass(), navLinks);
|
| | | add(navigationPanel);
|
| | |
|
| | | add(new ExternalLink("syndication", SyndicationServlet.asLink(getRequest()
|
| | |
| | | return new BugtraqProcessor(app().settings());
|
| | | }
|
| | |
|
| | | private Map<String, PageRegistration> registerPages() {
|
| | | private List<NavLink> registerNavLinks() {
|
| | | PageParameters params = null;
|
| | | if (!StringUtils.isEmpty(repositoryName)) {
|
| | | params = WicketUtils.newRepositoryParameter(repositoryName);
|
| | | }
|
| | | Map<String, PageRegistration> pages = new LinkedHashMap<String, PageRegistration>();
|
| | | List<NavLink> navLinks = new ArrayList<NavLink>();
|
| | |
|
| | | Repository r = getRepository();
|
| | | RepositoryModel model = getRepositoryModel();
|
| | |
|
| | | // standard links
|
| | | if (RefLogUtils.getRefLogBranch(r) == null) {
|
| | | pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params));
|
| | | navLinks.add(new PageNavLink("gb.summary", SummaryPage.class, params));
|
| | | } else {
|
| | | pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params));
|
| | | // pages.put("overview", new PageRegistration("gb.overview", OverviewPage.class, params));
|
| | | pages.put("reflog", new PageRegistration("gb.reflog", ReflogPage.class, params));
|
| | | navLinks.add(new PageNavLink("gb.summary", SummaryPage.class, params));
|
| | | // pages.put("overview", new PageRegistration("gb.overview", OverviewPage.class, params));
|
| | | navLinks.add(new PageNavLink("gb.reflog", ReflogPage.class, params));
|
| | | }
|
| | | pages.put("commits", new PageRegistration("gb.commits", LogPage.class, params));
|
| | | pages.put("tree", new PageRegistration("gb.tree", TreePage.class, params));
|
| | | if (app().tickets().isReady() && (app().tickets().isAcceptingNewTickets(getRepositoryModel()) || app().tickets().hasTickets(getRepositoryModel()))) {
|
| | | PageParameters tParams = new PageParameters(params);
|
| | | for (String state : TicketsPage.openStatii) {
|
| | | tParams.add(Lucene.status.name(), state);
|
| | | }
|
| | | pages.put("tickets", new PageRegistration("gb.tickets", TicketsPage.class, tParams)); |
| | |
|
| | | if (!model.hasCommits) {
|
| | | return navLinks;
|
| | | }
|
| | |
|
| | | navLinks.add(new PageNavLink("gb.commits", LogPage.class, params));
|
| | | navLinks.add(new PageNavLink("gb.tree", TreePage.class, params));
|
| | | if (app().tickets().isReady() && (app().tickets().isAcceptingNewTickets(model) || app().tickets().hasTickets(model))) {
|
| | | PageParameters tParams = WicketUtils.newOpenTicketsParameter(repositoryName);
|
| | | navLinks.add(new PageNavLink("gb.tickets", TicketsPage.class, tParams)); |
| | | } |
| | | pages.put("docs", new PageRegistration("gb.docs", DocsPage.class, params, true));
|
| | | navLinks.add(new PageNavLink("gb.docs", DocsPage.class, params, true));
|
| | | if (app().settings().getBoolean(Keys.web.allowForking, true)) {
|
| | | pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params, true));
|
| | | navLinks.add(new PageNavLink("gb.forks", ForksPage.class, params, true));
|
| | | }
|
| | | pages.put("compare", new PageRegistration("gb.compare", ComparePage.class, params, true)); |
| | | navLinks.add(new PageNavLink("gb.compare", ComparePage.class, params, true)); |
| | |
|
| | | // conditional links
|
| | | // per-repository extra page links
|
| | | // per-repository extra navlinks
|
| | | if (JGitUtils.getPagesBranch(r) != null) {
|
| | | OtherPageLink pagesLink = new OtherPageLink("gb.pages", PagesServlet.asLink(
|
| | | ExternalNavLink pagesLink = new ExternalNavLink("gb.pages", PagesServlet.asLink(
|
| | | getRequest().getRelativePathPrefixToContextRoot(), repositoryName, null), true);
|
| | | pages.put("pages", pagesLink);
|
| | | navLinks.add(pagesLink);
|
| | | }
|
| | |
|
| | | // Conditionally add edit link
|
| | | showAdmin = false;
|
| | | if (app().settings().getBoolean(Keys.web.authenticateAdminPages, true)) {
|
| | | boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, false);
|
| | | showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin();
|
| | | } else {
|
| | | showAdmin = app().settings().getBoolean(Keys.web.allowAdministration, false);
|
| | | UserModel user = UserModel.ANONYMOUS;
|
| | | if (GitBlitWebSession.get().isLoggedIn()) {
|
| | | user = GitBlitWebSession.get().getUser();
|
| | | }
|
| | | isOwner = GitBlitWebSession.get().isLoggedIn()
|
| | | && (model.isOwner(GitBlitWebSession.get()
|
| | | .getUsername()));
|
| | | return pages;
|
| | |
|
| | | // add repository nav link extensions
|
| | | List<RepositoryNavLinkExtension> extensions = app().plugins().getExtensions(RepositoryNavLinkExtension.class);
|
| | | for (RepositoryNavLinkExtension ext : extensions) {
|
| | | navLinks.addAll(ext.getNavLinks(user, model));
|
| | | }
|
| | |
|
| | | return navLinks;
|
| | | }
|
| | |
|
| | | protected boolean allowForkControls() {
|
| | |
| | | }
|
| | |
|
| | | // (un)star link allows a user to star a repository
|
| | | if (user.isAuthenticated) {
|
| | | if (user.isAuthenticated && model.hasCommits) {
|
| | | PageParameters starParams = DeepCopier.copy(getPageParameters());
|
| | | starParams.put(PARAM_STAR, !user.getPreferences().isStarredRepository(model.name));
|
| | | String toggleStarUrl = getRequestCycle().urlFor(getClass(), starParams).toString();
|
| | |
| | | } else {
|
| | | String fork = app().repositories().getFork(user.username, model.name);
|
| | | boolean hasFork = fork != null;
|
| | | boolean canFork = user.canFork(model);
|
| | | boolean canFork = user.canFork(model) && model.hasCommits;
|
| | |
|
| | | if (hasFork || !canFork) {
|
| | | // user not allowed to fork or fork already exists or repo forbids forking
|
| | |
| | | <li class="dropdown">
|
| | | <a data-toggle="dropdown" class="dropdown-toggle" style="text-decoration: none;" href="#"><span wicket:id="username"></span> <b class="caret"></b></a>
|
| | | <ul class="dropdown-menu">
|
| | | <li style="color:#ccc;padding-left:15px;font-weight:bold;"><span wicket:id="displayName"></span></li>
|
| | | <li class="divider"></li>
|
| | | <li><a wicket:id="newRepository"><wicket:message key="gb.newRepository"></wicket:message></a></li>
|
| | | <li><a wicket:id="myProfile"><wicket:message key="gb.myProfile"></wicket:message></a></li>
|
| | | <li><a wicket:id="changePassword"><wicket:message key="gb.changePassword"></wicket:message></a></li>
|
| | | <li class="divider"></li>
|
| | | <span wicket:id="standardMenu"></span>
|
| | | <span wicket:id="adminMenu"></span>
|
| | | <span wicket:id="extensionsMenu"></span>
|
| | | <li><a wicket:id="logout"><wicket:message key="gb.logout"></wicket:message></a></li>
|
| | | </ul>
|
| | | </li>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="submenuFragment">
|
| | | <li style="color:#ccc;padding-left:15px;font-weight:bold;"><span wicket:id="submenuTitle"></span></li>
|
| | | <li wicket:id="submenuItem"><span wicket:id="submenuLink"></span></li>
|
| | | </wicket:fragment>
|
| | |
|
| | | </wicket:extend>
|
| | | </body>
|
| | |
| | | /*
|
| | | * 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.wicket.pages;
|
| | |
|
| | | import java.text.MessageFormat;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Arrays;
|
| | | import java.util.Calendar;
|
| | | import java.util.Collections;
|
| | | import java.util.Date;
|
| | | import java.util.HashMap;
|
| | | import java.util.HashSet;
|
| | | import java.util.LinkedHashSet;
|
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | | import java.util.Set;
|
| | | import java.util.TreeSet;
|
| | | import java.util.concurrent.atomic.AtomicInteger;
|
| | | import java.util.regex.Pattern;
|
| | |
|
| | | import org.apache.wicket.MarkupContainer;
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.behavior.HeaderContributor;
|
| | | import org.apache.wicket.markup.html.IHeaderContributor;
|
| | | import org.apache.wicket.markup.html.IHeaderResponse;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.PasswordTextField;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | | import org.apache.wicket.protocol.http.WebResponse;
|
| | |
|
| | | import com.gitblit.Constants;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.TeamModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.ModelUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.PageRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownToggleItem;
|
| | | import com.gitblit.wicket.SessionlessForm;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.GravatarImage;
|
| | | import com.gitblit.wicket.panels.NavigationPanel;
|
| | |
|
| | | /**
|
| | | * Root page is a topbar, navigable page like Repositories, Users, or
|
| | | * Federation.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public abstract class RootPage extends BasePage {
|
| | |
|
| | | boolean showAdmin;
|
| | |
|
| | | IModel<String> username = new Model<String>("");
|
| | | IModel<String> password = new Model<String>("");
|
| | | List<RepositoryModel> repositoryModels = new ArrayList<RepositoryModel>();
|
| | |
|
| | | public RootPage() {
|
| | | super();
|
| | | }
|
| | |
|
| | | public RootPage(PageParameters params) {
|
| | | super(params);
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void setupPage(String repositoryName, String pageName) {
|
| | |
|
| | | // CSS header overrides
|
| | | add(new HeaderContributor(new IHeaderContributor() {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void renderHead(IHeaderResponse response) {
|
| | | StringBuilder buffer = new StringBuilder();
|
| | | buffer.append("<style type=\"text/css\">\n");
|
| | | buffer.append(".navbar-inner {\n");
|
| | | final String headerBackground = app().settings().getString(Keys.web.headerBackgroundColor, null);
|
| | | if (!StringUtils.isEmpty(headerBackground)) {
|
| | | buffer.append(MessageFormat.format("background-color: {0};\n", headerBackground));
|
| | | }
|
| | | final String headerBorder = app().settings().getString(Keys.web.headerBorderColor, null);
|
| | | if (!StringUtils.isEmpty(headerBorder)) {
|
| | | buffer.append(MessageFormat.format("border-bottom: 1px solid {0} !important;\n", headerBorder));
|
| | | }
|
| | | buffer.append("}\n");
|
| | | final String headerBorderFocus = app().settings().getString(Keys.web.headerBorderFocusColor, null);
|
| | | if (!StringUtils.isEmpty(headerBorderFocus)) {
|
| | | buffer.append(".navbar ul li:focus, .navbar .active {\n");
|
| | | buffer.append(MessageFormat.format("border-bottom: 4px solid {0};\n", headerBorderFocus));
|
| | | buffer.append("}\n");
|
| | | }
|
| | | final String headerForeground = app().settings().getString(Keys.web.headerForegroundColor, null);
|
| | | if (!StringUtils.isEmpty(headerForeground)) {
|
| | | buffer.append(".navbar ul.nav li a {\n");
|
| | | buffer.append(MessageFormat.format("color: {0};\n", headerForeground));
|
| | | buffer.append("}\n");
|
| | | buffer.append(".navbar ul.nav .active a {\n");
|
| | | buffer.append(MessageFormat.format("color: {0};\n", headerForeground));
|
| | | buffer.append("}\n");
|
| | | }
|
| | | final String headerHover = app().settings().getString(Keys.web.headerHoverColor, null);
|
| | | if (!StringUtils.isEmpty(headerHover)) {
|
| | | buffer.append(".navbar ul.nav li a:hover {\n");
|
| | | buffer.append(MessageFormat.format("color: {0} !important;\n", headerHover));
|
| | | buffer.append("}\n");
|
| | | }
|
| | | buffer.append("</style>\n");
|
| | | response.renderString(buffer.toString());
|
| | | }
|
| | | }));
|
| | |
|
| | | boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, false);
|
| | | boolean authenticateAdmin = app().settings().getBoolean(Keys.web.authenticateAdminPages, true);
|
| | | boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, true);
|
| | |
|
| | | if (authenticateAdmin) {
|
| | | showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin();
|
| | | // authentication requires state and session
|
| | | setStatelessHint(false);
|
| | | } else {
|
| | | showAdmin = allowAdmin;
|
| | | if (authenticateView) {
|
| | | // authentication requires state and session
|
| | | setStatelessHint(false);
|
| | | } else {
|
| | | // no authentication required, no state and no session required
|
| | | setStatelessHint(true);
|
| | | }
|
| | | }
|
| | |
|
| | | if (authenticateView || authenticateAdmin) {
|
| | | if (GitBlitWebSession.get().isLoggedIn()) {
|
| | | UserMenu userFragment = new UserMenu("userPanel", "userMenuFragment", RootPage.this);
|
| | | add(userFragment);
|
| | | } else {
|
| | | LoginForm loginForm = new LoginForm("userPanel", "loginFormFragment", RootPage.this);
|
| | | add(loginForm);
|
| | | }
|
| | | } else {
|
| | | add(new Label("userPanel").setVisible(false));
|
| | | }
|
| | |
|
| | | boolean showRegistrations = app().federation().canFederate()
|
| | | && app().settings().getBoolean(Keys.web.showFederationRegistrations, false);
|
| | |
|
| | | // navigation links
|
| | | List<PageRegistration> pages = new ArrayList<PageRegistration>();
|
| | | if (!authenticateView || (authenticateView && GitBlitWebSession.get().isLoggedIn())) {
|
| | | pages.add(new PageRegistration(GitBlitWebSession.get().isLoggedIn() ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class,
|
| | | getRootPageParameters()));
|
| | | pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class,
|
| | | getRootPageParameters()));
|
| | | pages.add(new PageRegistration("gb.activity", ActivityPage.class, getRootPageParameters()));
|
| | | if (app().settings().getBoolean(Keys.web.allowLuceneIndexing, true)) {
|
| | | pages.add(new PageRegistration("gb.search", LuceneSearchPage.class));
|
| | | }
|
| | | if (showAdmin) {
|
| | | pages.add(new PageRegistration("gb.users", UsersPage.class));
|
| | | }
|
| | | if (showAdmin || showRegistrations) {
|
| | | pages.add(new PageRegistration("gb.federation", FederationPage.class));
|
| | | }
|
| | |
|
| | | if (!authenticateView || (authenticateView && GitBlitWebSession.get().isLoggedIn())) {
|
| | | addDropDownMenus(pages);
|
| | | }
|
| | | }
|
| | |
|
| | | NavigationPanel navPanel = new NavigationPanel("navPanel", getRootNavPageClass(), pages);
|
| | | add(navPanel);
|
| | |
|
| | | // display an error message cached from a redirect
|
| | | String cachedMessage = GitBlitWebSession.get().clearErrorMessage();
|
| | | if (!StringUtils.isEmpty(cachedMessage)) {
|
| | | error(cachedMessage);
|
| | | } else if (showAdmin) {
|
| | | int pendingProposals = app().federation().getPendingFederationProposals().size();
|
| | | if (pendingProposals == 1) {
|
| | | info(getString("gb.OneProposalToReview"));
|
| | | } else if (pendingProposals > 1) {
|
| | | info(MessageFormat.format(getString("gb.nFederationProposalsToReview"),
|
| | | pendingProposals));
|
| | | }
|
| | | }
|
| | |
|
| | | super.setupPage(repositoryName, pageName);
|
| | | }
|
| | |
|
| | | protected Class<? extends BasePage> getRootNavPageClass() {
|
| | | return getClass();
|
| | | }
|
| | |
|
| | | private PageParameters getRootPageParameters() {
|
| | | if (reusePageParameters()) {
|
| | | PageParameters pp = getPageParameters();
|
| | | if (pp != null) {
|
| | | PageParameters params = new PageParameters(pp);
|
| | | // remove named project parameter
|
| | | params.remove("p");
|
| | |
|
| | | // remove named repository parameter
|
| | | params.remove("r");
|
| | |
|
| | | // remove named user parameter
|
| | | params.remove("user");
|
| | |
|
| | | // remove days back parameter if it is the default value
|
| | | if (params.containsKey("db")
|
| | | && params.getInt("db") == app().settings().getInteger(Keys.web.activityDuration, 7)) {
|
| | | params.remove("db");
|
| | | }
|
| | | return params;
|
| | | }
|
| | | }
|
| | | return null;
|
| | | }
|
| | |
|
| | | protected boolean reusePageParameters() {
|
| | | return false;
|
| | | }
|
| | |
|
| | | private void loginUser(UserModel user) {
|
| | | if (user != null) {
|
| | | // Set the user into the session
|
| | | GitBlitWebSession session = GitBlitWebSession.get();
|
| | | // issue 62: fix session fixation vulnerability
|
| | | session.replaceSession();
|
| | | session.setUser(user);
|
| | |
|
| | | // Set Cookie
|
| | | if (app().settings().getBoolean(Keys.web.allowCookieAuthentication, false)) {
|
| | | WebResponse response = (WebResponse) getRequestCycle().getResponse();
|
| | | app().authentication().setCookie(response.getHttpServletResponse(), user);
|
| | | }
|
| | |
|
| | | if (!session.continueRequest()) {
|
| | | PageParameters params = getPageParameters();
|
| | | if (params == null) {
|
| | | // redirect to this page
|
| | | setResponsePage(getClass());
|
| | | } else {
|
| | | // Strip username and password and redirect to this page
|
| | | params.remove("username");
|
| | | params.remove("password");
|
| | | setResponsePage(getClass(), params);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | protected List<RepositoryModel> getRepositoryModels() {
|
| | | if (repositoryModels.isEmpty()) {
|
| | | final UserModel user = GitBlitWebSession.get().getUser();
|
| | | List<RepositoryModel> repositories = app().repositories().getRepositoryModels(user);
|
| | | repositoryModels.addAll(repositories);
|
| | | Collections.sort(repositoryModels);
|
| | | }
|
| | | return repositoryModels;
|
| | | }
|
| | |
|
| | | protected void addDropDownMenus(List<PageRegistration> pages) {
|
| | |
|
| | | }
|
| | |
|
| | | protected List<DropDownMenuItem> getRepositoryFilterItems(PageParameters params) {
|
| | | final UserModel user = GitBlitWebSession.get().getUser();
|
| | | Set<DropDownMenuItem> filters = new LinkedHashSet<DropDownMenuItem>();
|
| | | List<RepositoryModel> repositories = getRepositoryModels();
|
| | |
|
| | | // accessible repositories by federation set
|
| | | Map<String, AtomicInteger> setMap = new HashMap<String, AtomicInteger>();
|
| | | for (RepositoryModel repository : repositories) {
|
| | | for (String set : repository.federationSets) {
|
| | | String key = set.toLowerCase();
|
| | | if (setMap.containsKey(key)) {
|
| | | setMap.get(key).incrementAndGet();
|
| | | } else {
|
| | | setMap.put(key, new AtomicInteger(1));
|
| | | }
|
| | | }
|
| | | }
|
| | | if (setMap.size() > 0) {
|
| | | List<String> sets = new ArrayList<String>(setMap.keySet());
|
| | | Collections.sort(sets);
|
| | | for (String set : sets) {
|
| | | filters.add(new DropDownToggleItem(MessageFormat.format("{0} ({1})", set,
|
| | | setMap.get(set).get()), "set", set, params));
|
| | | }
|
| | | // divider
|
| | | filters.add(new DropDownMenuItem());
|
| | | }
|
| | |
|
| | | // user's team memberships
|
| | | if (user != null && user.teams.size() > 0) {
|
| | | List<TeamModel> teams = new ArrayList<TeamModel>(user.teams);
|
| | | Collections.sort(teams);
|
| | | for (TeamModel team : teams) {
|
| | | filters.add(new DropDownToggleItem(MessageFormat.format("{0} ({1})", team.name,
|
| | | team.repositories.size()), "team", team.name, params));
|
| | | }
|
| | | // divider
|
| | | filters.add(new DropDownMenuItem());
|
| | | }
|
| | |
|
| | | // custom filters
|
| | | String customFilters = app().settings().getString(Keys.web.customFilters, null);
|
| | | if (!StringUtils.isEmpty(customFilters)) {
|
| | | boolean addedExpression = false;
|
| | | List<String> expressions = StringUtils.getStringsFromValue(customFilters, "!!!");
|
| | | for (String expression : expressions) {
|
| | | if (!StringUtils.isEmpty(expression)) {
|
| | | addedExpression = true;
|
| | | filters.add(new DropDownToggleItem(null, "x", expression, params));
|
| | | }
|
| | | }
|
| | | // if we added any custom expressions, add a divider
|
| | | if (addedExpression) {
|
| | | filters.add(new DropDownMenuItem());
|
| | | }
|
| | | }
|
| | | return new ArrayList<DropDownMenuItem>(filters);
|
| | | }
|
| | |
|
| | | protected List<DropDownMenuItem> getTimeFilterItems(PageParameters params) {
|
| | | // days back choices - additive parameters
|
| | | int daysBack = app().settings().getInteger(Keys.web.activityDuration, 7);
|
| | | int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30);
|
| | | if (daysBack < 1) {
|
| | | daysBack = 7;
|
| | | }
|
| | | if (daysBack > maxDaysBack) {
|
| | | daysBack = maxDaysBack;
|
| | | }
|
| | | PageParameters clonedParams;
|
| | | if (params == null) {
|
| | | clonedParams = new PageParameters();
|
| | | } else {
|
| | | clonedParams = new PageParameters(params);
|
| | | }
|
| | |
|
| | | if (!clonedParams.containsKey("db")) {
|
| | | clonedParams.put("db", daysBack);
|
| | | }
|
| | |
|
| | | List<DropDownMenuItem> items = new ArrayList<DropDownMenuItem>();
|
| | | Set<Integer> choicesSet = new TreeSet<Integer>(app().settings().getIntegers(Keys.web.activityDurationChoices));
|
| | | if (choicesSet.isEmpty()) {
|
| | | choicesSet.addAll(Arrays.asList(1, 3, 7, 14, 21, 28));
|
| | | }
|
| | | List<Integer> choices = new ArrayList<Integer>(choicesSet);
|
| | | Collections.sort(choices);
|
| | | String lastDaysPattern = getString("gb.lastNDays");
|
| | | for (Integer db : choices) {
|
| | | if (db == 1) {
|
| | | items.add(new DropDownMenuItem(getString("gb.time.today"), "db", db.toString(), clonedParams));
|
| | | } else {
|
| | | String txt = MessageFormat.format(lastDaysPattern, db);
|
| | | items.add(new DropDownMenuItem(txt, "db", db.toString(), clonedParams));
|
| | | }
|
| | | }
|
| | | items.add(new DropDownMenuItem());
|
| | | return items;
|
| | | }
|
| | |
|
| | | protected List<RepositoryModel> getRepositories(PageParameters params) {
|
| | | if (params == null) {
|
| | | return getRepositoryModels();
|
| | | }
|
| | |
|
| | | boolean hasParameter = false;
|
| | | String projectName = WicketUtils.getProjectName(params);
|
| | | String userName = WicketUtils.getUsername(params);
|
| | | if (StringUtils.isEmpty(projectName)) {
|
| | | if (!StringUtils.isEmpty(userName)) {
|
| | | projectName = ModelUtils.getPersonalPath(userName);
|
| | | }
|
| | | }
|
| | | String repositoryName = WicketUtils.getRepositoryName(params);
|
| | | String set = WicketUtils.getSet(params);
|
| | | String regex = WicketUtils.getRegEx(params);
|
| | | String team = WicketUtils.getTeam(params);
|
| | | int daysBack = params.getInt("db", 0);
|
| | | int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30);
|
| | |
|
| | | List<RepositoryModel> availableModels = getRepositoryModels();
|
| | | Set<RepositoryModel> models = new HashSet<RepositoryModel>();
|
| | |
|
| | | if (!StringUtils.isEmpty(repositoryName)) {
|
| | | // try named repository
|
| | | hasParameter = true;
|
| | | for (RepositoryModel model : availableModels) {
|
| | | if (model.name.equalsIgnoreCase(repositoryName)) {
|
| | | models.add(model);
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (!StringUtils.isEmpty(projectName)) {
|
| | | // try named project
|
| | | hasParameter = true;
|
| | | if (projectName.equalsIgnoreCase(app().settings().getString(Keys.web.repositoryRootGroupName, "main"))) {
|
| | | // root project/group
|
| | | for (RepositoryModel model : availableModels) {
|
| | | if (model.name.indexOf('/') == -1) {
|
| | | models.add(model);
|
| | | }
|
| | | }
|
| | | } else {
|
| | | // named project/group
|
| | | String group = projectName.toLowerCase() + "/";
|
| | | for (RepositoryModel model : availableModels) {
|
| | | if (model.name.toLowerCase().startsWith(group)) {
|
| | | models.add(model);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (!StringUtils.isEmpty(regex)) {
|
| | | // filter the repositories by the regex
|
| | | hasParameter = true;
|
| | | Pattern pattern = Pattern.compile(regex);
|
| | | for (RepositoryModel model : availableModels) {
|
| | | if (pattern.matcher(model.name).find()) {
|
| | | models.add(model);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (!StringUtils.isEmpty(set)) {
|
| | | // filter the repositories by the specified sets
|
| | | hasParameter = true;
|
| | | List<String> sets = StringUtils.getStringsFromValue(set, ",");
|
| | | for (RepositoryModel model : availableModels) {
|
| | | for (String curr : sets) {
|
| | | if (model.federationSets.contains(curr)) {
|
| | | models.add(model);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (!StringUtils.isEmpty(team)) {
|
| | | // filter the repositories by the specified teams
|
| | | hasParameter = true;
|
| | | List<String> teams = StringUtils.getStringsFromValue(team, ",");
|
| | |
|
| | | // need TeamModels first
|
| | | List<TeamModel> teamModels = new ArrayList<TeamModel>();
|
| | | for (String name : teams) {
|
| | | TeamModel teamModel = app().users().getTeamModel(name);
|
| | | if (teamModel != null) {
|
| | | teamModels.add(teamModel);
|
| | | }
|
| | | }
|
| | |
|
| | | // brute-force our way through finding the matching models
|
| | | for (RepositoryModel repositoryModel : availableModels) {
|
| | | for (TeamModel teamModel : teamModels) {
|
| | | if (teamModel.hasRepositoryPermission(repositoryModel.name)) {
|
| | | models.add(repositoryModel);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (!hasParameter) {
|
| | | models.addAll(availableModels);
|
| | | }
|
| | |
|
| | | // time-filter the list
|
| | | if (daysBack > 0) {
|
| | | if (maxDaysBack > 0 && daysBack > maxDaysBack) {
|
| | | daysBack = maxDaysBack;
|
| | | }
|
| | | Calendar cal = Calendar.getInstance();
|
| | | cal.set(Calendar.HOUR_OF_DAY, 0);
|
| | | cal.set(Calendar.MINUTE, 0);
|
| | | cal.set(Calendar.SECOND, 0);
|
| | | cal.set(Calendar.MILLISECOND, 0);
|
| | | cal.add(Calendar.DATE, -1 * daysBack);
|
| | | Date threshold = cal.getTime();
|
| | | Set<RepositoryModel> timeFiltered = new HashSet<RepositoryModel>();
|
| | | for (RepositoryModel model : models) {
|
| | | if (model.lastChange.after(threshold)) {
|
| | | timeFiltered.add(model);
|
| | | }
|
| | | }
|
| | | models = timeFiltered;
|
| | | }
|
| | |
|
| | | List<RepositoryModel> list = new ArrayList<RepositoryModel>(models);
|
| | | Collections.sort(list);
|
| | | return list;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Inline login form.
|
| | | */
|
| | | private class LoginForm extends Fragment {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public LoginForm(String id, String markupId, MarkupContainer markupProvider) {
|
| | | super(id, markupId, markupProvider);
|
| | | setRenderBodyOnly(true);
|
| | |
|
| | | SessionlessForm<Void> loginForm = new SessionlessForm<Void>("loginForm", RootPage.this.getClass(), getPageParameters()) {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void onSubmit() {
|
| | | String username = RootPage.this.username.getObject();
|
| | | char[] password = RootPage.this.password.getObject().toCharArray();
|
| | |
|
| | | UserModel user = app().authentication().authenticate(username, password);
|
| | | if (user == null) {
|
| | | error(getString("gb.invalidUsernameOrPassword"));
|
| | | } else if (user.username.equals(Constants.FEDERATION_USER)) {
|
| | | // disallow the federation user from logging in via the
|
| | | // web ui
|
| | | error(getString("gb.invalidUsernameOrPassword"));
|
| | | user = null;
|
| | | } else {
|
| | | loginUser(user);
|
| | | }
|
| | | }
|
| | | };
|
| | | TextField<String> unameField = new TextField<String>("username", username);
|
| | | WicketUtils.setInputPlaceholder(unameField, markupProvider.getString("gb.username"));
|
| | | loginForm.add(unameField);
|
| | | PasswordTextField pwField = new PasswordTextField("password", password);
|
| | | WicketUtils.setInputPlaceholder(pwField, markupProvider.getString("gb.password"));
|
| | | loginForm.add(pwField);
|
| | | add(loginForm);
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * Menu for the authenticated user.
|
| | | */
|
| | | class UserMenu extends Fragment {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public UserMenu(String id, String markupId, MarkupContainer markupProvider) {
|
| | | super(id, markupId, markupProvider);
|
| | | setRenderBodyOnly(true);
|
| | |
|
| | | GitBlitWebSession session = GitBlitWebSession.get();
|
| | | UserModel user = session.getUser();
|
| | | boolean editCredentials = app().authentication().supportsCredentialChanges(user);
|
| | | boolean standardLogin = session.authenticationType.isStandard();
|
| | |
|
| | | if (app().settings().getBoolean(Keys.web.allowGravatar, true)) {
|
| | | add(new GravatarImage("username", user, "navbarGravatar", 20, false));
|
| | | } else {
|
| | | add(new Label("username", user.getDisplayName()));
|
| | | }
|
| | |
|
| | | add(new Label("displayName", user.getDisplayName()));
|
| | |
|
| | | add(new BookmarkablePageLink<Void>("newRepository",
|
| | | EditRepositoryPage.class).setVisible(user.canAdmin() || user.canCreate()));
|
| | |
|
| | | add(new BookmarkablePageLink<Void>("myProfile",
|
| | | UserPage.class, WicketUtils.newUsernameParameter(user.username)));
|
| | |
|
| | | add(new BookmarkablePageLink<Void>("changePassword",
|
| | | ChangePasswordPage.class).setVisible(editCredentials));
|
| | |
|
| | | add(new BookmarkablePageLink<Void>("logout",
|
| | | LogoutPage.class).setVisible(standardLogin));
|
| | | }
|
| | | }
|
| | | }
|
| | | /* |
| | | * 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.wicket.pages; |
| | | |
| | | import java.text.MessageFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Calendar; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.TreeSet; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | import java.util.regex.Pattern; |
| | | |
| | | import org.apache.wicket.MarkupContainer; |
| | | import org.apache.wicket.PageParameters; |
| | | import org.apache.wicket.behavior.HeaderContributor; |
| | | import org.apache.wicket.markup.html.IHeaderContributor; |
| | | import org.apache.wicket.markup.html.IHeaderResponse; |
| | | import org.apache.wicket.markup.html.basic.Label; |
| | | import org.apache.wicket.markup.html.form.PasswordTextField; |
| | | import org.apache.wicket.markup.html.form.TextField; |
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink; |
| | | import org.apache.wicket.markup.html.panel.Fragment; |
| | | import org.apache.wicket.markup.repeater.Item; |
| | | import org.apache.wicket.markup.repeater.data.DataView; |
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider; |
| | | import org.apache.wicket.model.IModel; |
| | | import org.apache.wicket.model.Model; |
| | | import org.apache.wicket.protocol.http.WebResponse; |
| | | |
| | | import com.gitblit.Constants; |
| | | import com.gitblit.Keys; |
| | | import com.gitblit.extensions.NavLinkExtension; |
| | | import com.gitblit.extensions.UserMenuExtension; |
| | | import com.gitblit.models.Menu.ExternalLinkMenuItem; |
| | | import com.gitblit.models.Menu.MenuDivider; |
| | | import com.gitblit.models.Menu.MenuItem; |
| | | import com.gitblit.models.Menu.PageLinkMenuItem; |
| | | import com.gitblit.models.Menu.ParameterMenuItem; |
| | | import com.gitblit.models.Menu.ToggleMenuItem; |
| | | import com.gitblit.models.NavLink; |
| | | import com.gitblit.models.NavLink.PageNavLink; |
| | | import com.gitblit.models.RepositoryModel; |
| | | import com.gitblit.models.TeamModel; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.utils.ModelUtils; |
| | | import com.gitblit.utils.StringUtils; |
| | | import com.gitblit.wicket.GitBlitWebSession; |
| | | import com.gitblit.wicket.SessionlessForm; |
| | | import com.gitblit.wicket.WicketUtils; |
| | | import com.gitblit.wicket.panels.GravatarImage; |
| | | import com.gitblit.wicket.panels.LinkPanel; |
| | | import com.gitblit.wicket.panels.NavigationPanel; |
| | | |
| | | /** |
| | | * Root page is a topbar, navigable page like Repositories, Users, or |
| | | * Federation. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public abstract class RootPage extends BasePage { |
| | | |
| | | boolean showAdmin; |
| | | |
| | | IModel<String> username = new Model<String>(""); |
| | | IModel<String> password = new Model<String>(""); |
| | | List<RepositoryModel> repositoryModels = new ArrayList<RepositoryModel>(); |
| | | |
| | | public RootPage() { |
| | | super(); |
| | | } |
| | | |
| | | public RootPage(PageParameters params) { |
| | | super(params); |
| | | } |
| | | |
| | | @Override |
| | | protected void setupPage(String repositoryName, String pageName) { |
| | | |
| | | // CSS header overrides |
| | | add(new HeaderContributor(new IHeaderContributor() { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void renderHead(IHeaderResponse response) { |
| | | StringBuilder buffer = new StringBuilder(); |
| | | buffer.append("<style type=\"text/css\">\n"); |
| | | buffer.append(".navbar-inner {\n"); |
| | | final String headerBackground = app().settings().getString(Keys.web.headerBackgroundColor, null); |
| | | if (!StringUtils.isEmpty(headerBackground)) { |
| | | buffer.append(MessageFormat.format("background-color: {0};\n", headerBackground)); |
| | | } |
| | | final String headerBorder = app().settings().getString(Keys.web.headerBorderColor, null); |
| | | if (!StringUtils.isEmpty(headerBorder)) { |
| | | buffer.append(MessageFormat.format("border-bottom: 1px solid {0} !important;\n", headerBorder)); |
| | | } |
| | | buffer.append("}\n"); |
| | | final String headerBorderFocus = app().settings().getString(Keys.web.headerBorderFocusColor, null); |
| | | if (!StringUtils.isEmpty(headerBorderFocus)) { |
| | | buffer.append(".navbar ul li:focus, .navbar .active {\n"); |
| | | buffer.append(MessageFormat.format("border-bottom: 4px solid {0};\n", headerBorderFocus)); |
| | | buffer.append("}\n"); |
| | | } |
| | | final String headerForeground = app().settings().getString(Keys.web.headerForegroundColor, null); |
| | | if (!StringUtils.isEmpty(headerForeground)) { |
| | | buffer.append(".navbar ul.nav li a {\n"); |
| | | buffer.append(MessageFormat.format("color: {0};\n", headerForeground)); |
| | | buffer.append("}\n"); |
| | | buffer.append(".navbar ul.nav .active a {\n"); |
| | | buffer.append(MessageFormat.format("color: {0};\n", headerForeground)); |
| | | buffer.append("}\n"); |
| | | } |
| | | final String headerHover = app().settings().getString(Keys.web.headerHoverColor, null); |
| | | if (!StringUtils.isEmpty(headerHover)) { |
| | | buffer.append(".navbar ul.nav li a:hover {\n"); |
| | | buffer.append(MessageFormat.format("color: {0} !important;\n", headerHover)); |
| | | buffer.append("}\n"); |
| | | } |
| | | buffer.append("</style>\n"); |
| | | response.renderString(buffer.toString()); |
| | | } |
| | | })); |
| | | |
| | | boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, false); |
| | | boolean authenticateAdmin = app().settings().getBoolean(Keys.web.authenticateAdminPages, true); |
| | | boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, true); |
| | | boolean allowLucene = app().settings().getBoolean(Keys.web.allowLuceneIndexing, true); |
| | | boolean isLoggedIn = GitBlitWebSession.get().isLoggedIn(); |
| | | |
| | | if (authenticateAdmin) { |
| | | showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin(); |
| | | // authentication requires state and session |
| | | setStatelessHint(false); |
| | | } else { |
| | | showAdmin = allowAdmin; |
| | | if (authenticateView) { |
| | | // authentication requires state and session |
| | | setStatelessHint(false); |
| | | } else { |
| | | // no authentication required, no state and no session required |
| | | setStatelessHint(true); |
| | | } |
| | | } |
| | | |
| | | if (authenticateView || authenticateAdmin) { |
| | | if (isLoggedIn) { |
| | | UserMenu userFragment = new UserMenu("userPanel", "userMenuFragment", RootPage.this); |
| | | add(userFragment); |
| | | } else { |
| | | LoginForm loginForm = new LoginForm("userPanel", "loginFormFragment", RootPage.this); |
| | | add(loginForm); |
| | | } |
| | | } else { |
| | | add(new Label("userPanel").setVisible(false)); |
| | | } |
| | | |
| | | // navigation links |
| | | List<NavLink> navLinks = new ArrayList<NavLink>(); |
| | | if (!authenticateView || (authenticateView && isLoggedIn)) { |
| | | navLinks.add(new PageNavLink(isLoggedIn ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class, |
| | | getRootPageParameters())); |
| | | if (isLoggedIn && app().tickets().isReady()) { |
| | | navLinks.add(new PageNavLink("gb.myTickets", MyTicketsPage.class)); |
| | | } |
| | | navLinks.add(new PageNavLink("gb.repositories", RepositoriesPage.class, |
| | | getRootPageParameters())); |
| | | navLinks.add(new PageNavLink("gb.activity", ActivityPage.class, getRootPageParameters())); |
| | | if (allowLucene) { |
| | | navLinks.add(new PageNavLink("gb.search", LuceneSearchPage.class)); |
| | | } |
| | | |
| | | if (!authenticateView || (authenticateView && isLoggedIn)) { |
| | | addDropDownMenus(navLinks); |
| | | } |
| | | |
| | | UserModel user = UserModel.ANONYMOUS; |
| | | if (isLoggedIn) { |
| | | user = GitBlitWebSession.get().getUser(); |
| | | } |
| | | |
| | | // add nav link extensions |
| | | List<NavLinkExtension> extensions = app().plugins().getExtensions(NavLinkExtension.class); |
| | | for (NavLinkExtension ext : extensions) { |
| | | navLinks.addAll(ext.getNavLinks(user)); |
| | | } |
| | | } |
| | | |
| | | NavigationPanel navPanel = new NavigationPanel("navPanel", getRootNavPageClass(), navLinks); |
| | | add(navPanel); |
| | | |
| | | // display an error message cached from a redirect |
| | | String cachedMessage = GitBlitWebSession.get().clearErrorMessage(); |
| | | if (!StringUtils.isEmpty(cachedMessage)) { |
| | | error(cachedMessage); |
| | | } else if (showAdmin) { |
| | | int pendingProposals = app().federation().getPendingFederationProposals().size(); |
| | | if (pendingProposals == 1) { |
| | | info(getString("gb.OneProposalToReview")); |
| | | } else if (pendingProposals > 1) { |
| | | info(MessageFormat.format(getString("gb.nFederationProposalsToReview"), |
| | | pendingProposals)); |
| | | } |
| | | } |
| | | |
| | | super.setupPage(repositoryName, pageName); |
| | | } |
| | | |
| | | protected Class<? extends BasePage> getRootNavPageClass() { |
| | | return getClass(); |
| | | } |
| | | |
| | | private PageParameters getRootPageParameters() { |
| | | if (reusePageParameters()) { |
| | | PageParameters pp = getPageParameters(); |
| | | if (pp != null) { |
| | | PageParameters params = new PageParameters(pp); |
| | | // remove named project parameter |
| | | params.remove("p"); |
| | | |
| | | // remove named repository parameter |
| | | params.remove("r"); |
| | | |
| | | // remove named user parameter |
| | | params.remove("user"); |
| | | |
| | | // remove days back parameter if it is the default value |
| | | if (params.containsKey("db") |
| | | && params.getInt("db") == app().settings().getInteger(Keys.web.activityDuration, 7)) { |
| | | params.remove("db"); |
| | | } |
| | | return params; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | protected boolean reusePageParameters() { |
| | | return false; |
| | | } |
| | | |
| | | private void loginUser(UserModel user) { |
| | | if (user != null) { |
| | | // Set the user into the session |
| | | GitBlitWebSession session = GitBlitWebSession.get(); |
| | | // issue 62: fix session fixation vulnerability |
| | | session.replaceSession(); |
| | | session.setUser(user); |
| | | |
| | | // Set Cookie |
| | | if (app().settings().getBoolean(Keys.web.allowCookieAuthentication, false)) { |
| | | WebResponse response = (WebResponse) getRequestCycle().getResponse(); |
| | | app().authentication().setCookie(response.getHttpServletResponse(), user); |
| | | } |
| | | |
| | | if (!session.continueRequest()) { |
| | | PageParameters params = getPageParameters(); |
| | | if (params == null) { |
| | | // redirect to this page |
| | | setResponsePage(getClass()); |
| | | } else { |
| | | // Strip username and password and redirect to this page |
| | | params.remove("username"); |
| | | params.remove("password"); |
| | | setResponsePage(getClass(), params); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected List<RepositoryModel> getRepositoryModels() { |
| | | if (repositoryModels.isEmpty()) { |
| | | final UserModel user = GitBlitWebSession.get().getUser(); |
| | | List<RepositoryModel> repositories = app().repositories().getRepositoryModels(user); |
| | | repositoryModels.addAll(repositories); |
| | | Collections.sort(repositoryModels); |
| | | } |
| | | return repositoryModels; |
| | | } |
| | | |
| | | protected void addDropDownMenus(List<NavLink> navLinks) { |
| | | |
| | | } |
| | | |
| | | protected List<com.gitblit.models.Menu.MenuItem> getRepositoryFilterItems(PageParameters params) { |
| | | final UserModel user = GitBlitWebSession.get().getUser(); |
| | | Set<MenuItem> filters = new LinkedHashSet<MenuItem>(); |
| | | List<RepositoryModel> repositories = getRepositoryModels(); |
| | | |
| | | // accessible repositories by federation set |
| | | Map<String, AtomicInteger> setMap = new HashMap<String, AtomicInteger>(); |
| | | for (RepositoryModel repository : repositories) { |
| | | for (String set : repository.federationSets) { |
| | | String key = set.toLowerCase(); |
| | | if (setMap.containsKey(key)) { |
| | | setMap.get(key).incrementAndGet(); |
| | | } else { |
| | | setMap.put(key, new AtomicInteger(1)); |
| | | } |
| | | } |
| | | } |
| | | if (setMap.size() > 0) { |
| | | List<String> sets = new ArrayList<String>(setMap.keySet()); |
| | | Collections.sort(sets); |
| | | for (String set : sets) { |
| | | filters.add(new ToggleMenuItem(MessageFormat.format("{0} ({1})", set, |
| | | setMap.get(set).get()), "set", set, params)); |
| | | } |
| | | // divider |
| | | filters.add(new MenuDivider()); |
| | | } |
| | | |
| | | // user's team memberships |
| | | if (user != null && user.teams.size() > 0) { |
| | | List<TeamModel> teams = new ArrayList<TeamModel>(user.teams); |
| | | Collections.sort(teams); |
| | | for (TeamModel team : teams) { |
| | | filters.add(new ToggleMenuItem(MessageFormat.format("{0} ({1})", team.name, |
| | | team.repositories.size()), "team", team.name, params)); |
| | | } |
| | | // divider |
| | | filters.add(new MenuDivider()); |
| | | } |
| | | |
| | | // custom filters |
| | | String customFilters = app().settings().getString(Keys.web.customFilters, null); |
| | | if (!StringUtils.isEmpty(customFilters)) { |
| | | boolean addedExpression = false; |
| | | List<String> expressions = StringUtils.getStringsFromValue(customFilters, "!!!"); |
| | | for (String expression : expressions) { |
| | | if (!StringUtils.isEmpty(expression)) { |
| | | addedExpression = true; |
| | | filters.add(new ToggleMenuItem(null, "x", expression, params)); |
| | | } |
| | | } |
| | | // if we added any custom expressions, add a divider |
| | | if (addedExpression) { |
| | | filters.add(new MenuDivider()); |
| | | } |
| | | } |
| | | return new ArrayList<MenuItem>(filters); |
| | | } |
| | | |
| | | protected List<MenuItem> getTimeFilterItems(PageParameters params) { |
| | | // days back choices - additive parameters |
| | | int daysBack = app().settings().getInteger(Keys.web.activityDuration, 7); |
| | | int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30); |
| | | if (daysBack < 1) { |
| | | daysBack = 7; |
| | | } |
| | | if (daysBack > maxDaysBack) { |
| | | daysBack = maxDaysBack; |
| | | } |
| | | PageParameters clonedParams; |
| | | if (params == null) { |
| | | clonedParams = new PageParameters(); |
| | | } else { |
| | | clonedParams = new PageParameters(params); |
| | | } |
| | | |
| | | if (!clonedParams.containsKey("db")) { |
| | | clonedParams.put("db", daysBack); |
| | | } |
| | | |
| | | List<MenuItem> items = new ArrayList<MenuItem>(); |
| | | Set<Integer> choicesSet = new TreeSet<Integer>(app().settings().getIntegers(Keys.web.activityDurationChoices)); |
| | | if (choicesSet.isEmpty()) { |
| | | choicesSet.addAll(Arrays.asList(1, 3, 7, 14, 21, 28)); |
| | | } |
| | | List<Integer> choices = new ArrayList<Integer>(choicesSet); |
| | | Collections.sort(choices); |
| | | String lastDaysPattern = getString("gb.lastNDays"); |
| | | for (Integer db : choices) { |
| | | if (db == 1) { |
| | | items.add(new ParameterMenuItem(getString("gb.time.today"), "db", db.toString(), clonedParams)); |
| | | } else { |
| | | String txt = MessageFormat.format(lastDaysPattern, db); |
| | | items.add(new ParameterMenuItem(txt, "db", db.toString(), clonedParams)); |
| | | } |
| | | } |
| | | items.add(new MenuDivider()); |
| | | return items; |
| | | } |
| | | |
| | | protected List<RepositoryModel> getRepositories(PageParameters params) { |
| | | if (params == null) { |
| | | return getRepositoryModels(); |
| | | } |
| | | |
| | | boolean hasParameter = false; |
| | | String projectName = WicketUtils.getProjectName(params); |
| | | String userName = WicketUtils.getUsername(params); |
| | | if (StringUtils.isEmpty(projectName)) { |
| | | if (!StringUtils.isEmpty(userName)) { |
| | | projectName = ModelUtils.getPersonalPath(userName); |
| | | } |
| | | } |
| | | String repositoryName = WicketUtils.getRepositoryName(params); |
| | | String set = WicketUtils.getSet(params); |
| | | String regex = WicketUtils.getRegEx(params); |
| | | String team = WicketUtils.getTeam(params); |
| | | int daysBack = params.getInt("db", 0); |
| | | int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30); |
| | | |
| | | List<RepositoryModel> availableModels = getRepositoryModels(); |
| | | Set<RepositoryModel> models = new HashSet<RepositoryModel>(); |
| | | |
| | | if (!StringUtils.isEmpty(repositoryName)) { |
| | | // try named repository |
| | | hasParameter = true; |
| | | for (RepositoryModel model : availableModels) { |
| | | if (model.name.equalsIgnoreCase(repositoryName)) { |
| | | models.add(model); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!StringUtils.isEmpty(projectName)) { |
| | | // try named project |
| | | hasParameter = true; |
| | | if (projectName.equalsIgnoreCase(app().settings().getString(Keys.web.repositoryRootGroupName, "main"))) { |
| | | // root project/group |
| | | for (RepositoryModel model : availableModels) { |
| | | if (model.name.indexOf('/') == -1) { |
| | | models.add(model); |
| | | } |
| | | } |
| | | } else { |
| | | // named project/group |
| | | String group = projectName.toLowerCase() + "/"; |
| | | for (RepositoryModel model : availableModels) { |
| | | if (model.name.toLowerCase().startsWith(group)) { |
| | | models.add(model); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!StringUtils.isEmpty(regex)) { |
| | | // filter the repositories by the regex |
| | | hasParameter = true; |
| | | Pattern pattern = Pattern.compile(regex); |
| | | for (RepositoryModel model : availableModels) { |
| | | if (pattern.matcher(model.name).find()) { |
| | | models.add(model); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!StringUtils.isEmpty(set)) { |
| | | // filter the repositories by the specified sets |
| | | hasParameter = true; |
| | | List<String> sets = StringUtils.getStringsFromValue(set, ","); |
| | | for (RepositoryModel model : availableModels) { |
| | | for (String curr : sets) { |
| | | if (model.federationSets.contains(curr)) { |
| | | models.add(model); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!StringUtils.isEmpty(team)) { |
| | | // filter the repositories by the specified teams |
| | | hasParameter = true; |
| | | List<String> teams = StringUtils.getStringsFromValue(team, ","); |
| | | |
| | | // need TeamModels first |
| | | List<TeamModel> teamModels = new ArrayList<TeamModel>(); |
| | | for (String name : teams) { |
| | | TeamModel teamModel = app().users().getTeamModel(name); |
| | | if (teamModel != null) { |
| | | teamModels.add(teamModel); |
| | | } |
| | | } |
| | | |
| | | // brute-force our way through finding the matching models |
| | | for (RepositoryModel repositoryModel : availableModels) { |
| | | for (TeamModel teamModel : teamModels) { |
| | | if (teamModel.hasRepositoryPermission(repositoryModel.name)) { |
| | | models.add(repositoryModel); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!hasParameter) { |
| | | models.addAll(availableModels); |
| | | } |
| | | |
| | | // time-filter the list |
| | | if (daysBack > 0) { |
| | | if (maxDaysBack > 0 && daysBack > maxDaysBack) { |
| | | daysBack = maxDaysBack; |
| | | } |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.set(Calendar.HOUR_OF_DAY, 0); |
| | | cal.set(Calendar.MINUTE, 0); |
| | | cal.set(Calendar.SECOND, 0); |
| | | cal.set(Calendar.MILLISECOND, 0); |
| | | cal.add(Calendar.DATE, -1 * daysBack); |
| | | Date threshold = cal.getTime(); |
| | | Set<RepositoryModel> timeFiltered = new HashSet<RepositoryModel>(); |
| | | for (RepositoryModel model : models) { |
| | | if (model.lastChange.after(threshold)) { |
| | | timeFiltered.add(model); |
| | | } |
| | | } |
| | | models = timeFiltered; |
| | | } |
| | | |
| | | List<RepositoryModel> list = new ArrayList<RepositoryModel>(models); |
| | | Collections.sort(list); |
| | | return list; |
| | | } |
| | | |
| | | /** |
| | | * Inline login form. |
| | | */ |
| | | private class LoginForm extends Fragment { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public LoginForm(String id, String markupId, MarkupContainer markupProvider) { |
| | | super(id, markupId, markupProvider); |
| | | setRenderBodyOnly(true); |
| | | |
| | | SessionlessForm<Void> loginForm = new SessionlessForm<Void>("loginForm", RootPage.this.getClass(), getPageParameters()) { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void onSubmit() { |
| | | String username = RootPage.this.username.getObject(); |
| | | char[] password = RootPage.this.password.getObject().toCharArray(); |
| | | |
| | | UserModel user = app().authentication().authenticate(username, password); |
| | | if (user == null) { |
| | | error(getString("gb.invalidUsernameOrPassword")); |
| | | } else if (user.username.equals(Constants.FEDERATION_USER)) { |
| | | // disallow the federation user from logging in via the |
| | | // web ui |
| | | error(getString("gb.invalidUsernameOrPassword")); |
| | | user = null; |
| | | } else { |
| | | loginUser(user); |
| | | } |
| | | } |
| | | }; |
| | | TextField<String> unameField = new TextField<String>("username", username); |
| | | WicketUtils.setInputPlaceholder(unameField, markupProvider.getString("gb.username")); |
| | | loginForm.add(unameField); |
| | | PasswordTextField pwField = new PasswordTextField("password", password); |
| | | WicketUtils.setInputPlaceholder(pwField, markupProvider.getString("gb.password")); |
| | | loginForm.add(pwField); |
| | | add(loginForm); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Menu for the authenticated user. |
| | | */ |
| | | class UserMenu extends Fragment { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public UserMenu(String id, String markupId, MarkupContainer markupProvider) { |
| | | super(id, markupId, markupProvider); |
| | | setRenderBodyOnly(true); |
| | | } |
| | | |
| | | @Override |
| | | protected void onInitialize() { |
| | | super.onInitialize(); |
| | | |
| | | GitBlitWebSession session = GitBlitWebSession.get(); |
| | | UserModel user = session.getUser(); |
| | | boolean editCredentials = app().authentication().supportsCredentialChanges(user); |
| | | boolean standardLogin = session.authenticationType.isStandard(); |
| | | |
| | | if (app().settings().getBoolean(Keys.web.allowGravatar, true)) { |
| | | add(new GravatarImage("username", user, "navbarGravatar", 20, false)); |
| | | } else { |
| | | add(new Label("username", user.getDisplayName())); |
| | | } |
| | | |
| | | List<MenuItem> standardItems = new ArrayList<MenuItem>(); |
| | | standardItems.add(new MenuDivider()); |
| | | if (user.canAdmin() || user.canCreate()) { |
| | | standardItems.add(new PageLinkMenuItem("gb.newRepository", app().getNewRepositoryPage())); |
| | | } |
| | | standardItems.add(new PageLinkMenuItem("gb.myProfile", UserPage.class, |
| | | WicketUtils.newUsernameParameter(user.username))); |
| | | if (editCredentials) { |
| | | standardItems.add(new PageLinkMenuItem("gb.changePassword", ChangePasswordPage.class)); |
| | | } |
| | | standardItems.add(new MenuDivider()); |
| | | add(newSubmenu("standardMenu", user.getDisplayName(), standardItems)); |
| | | |
| | | if (showAdmin) { |
| | | // admin menu |
| | | List<MenuItem> adminItems = new ArrayList<MenuItem>(); |
| | | adminItems.add(new MenuDivider()); |
| | | adminItems.add(new PageLinkMenuItem("gb.users", UsersPage.class)); |
| | | adminItems.add(new PageLinkMenuItem("gb.teams", TeamsPage.class)); |
| | | |
| | | boolean showRegistrations = app().federation().canFederate() |
| | | && app().settings().getBoolean(Keys.web.showFederationRegistrations, false); |
| | | if (showRegistrations) { |
| | | adminItems.add(new PageLinkMenuItem("gb.federation", FederationPage.class)); |
| | | } |
| | | adminItems.add(new MenuDivider()); |
| | | |
| | | add(newSubmenu("adminMenu", getString("gb.administration"), adminItems)); |
| | | } else { |
| | | add(new Label("adminMenu").setVisible(false)); |
| | | } |
| | | |
| | | // plugin extension items |
| | | List<MenuItem> extensionItems = new ArrayList<MenuItem>(); |
| | | List<UserMenuExtension> extensions = app().plugins().getExtensions(UserMenuExtension.class); |
| | | for (UserMenuExtension ext : extensions) { |
| | | List<MenuItem> items = ext.getMenuItems(user); |
| | | extensionItems.addAll(items); |
| | | } |
| | | |
| | | if (extensionItems.isEmpty()) { |
| | | // no extension items |
| | | add(new Label("extensionsMenu").setVisible(false)); |
| | | } else { |
| | | // found extension items |
| | | extensionItems.add(0, new MenuDivider()); |
| | | add(newSubmenu("extensionsMenu", getString("gb.extensions"), extensionItems)); |
| | | extensionItems.add(new MenuDivider()); |
| | | } |
| | | |
| | | add(new BookmarkablePageLink<Void>("logout", |
| | | LogoutPage.class).setVisible(standardLogin)); |
| | | } |
| | | |
| | | /** |
| | | * Creates a submenu. This is not actually submenu because we're using |
| | | * an older Twitter Bootstrap which is pre-submenu. |
| | | * |
| | | * @param wicketId |
| | | * @param submenuTitle |
| | | * @param menuItems |
| | | * @return a submenu fragment |
| | | */ |
| | | private Fragment newSubmenu(String wicketId, String submenuTitle, List<MenuItem> menuItems) { |
| | | Fragment submenu = new Fragment(wicketId, "submenuFragment", this); |
| | | submenu.add(new Label("submenuTitle", submenuTitle).setRenderBodyOnly(true)); |
| | | ListDataProvider<MenuItem> menuItemsDp = new ListDataProvider<MenuItem>(menuItems); |
| | | DataView<MenuItem> submenuItems = new DataView<MenuItem>("submenuItem", menuItemsDp) { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void populateItem(final Item<MenuItem> menuItem) { |
| | | final MenuItem item = menuItem.getModelObject(); |
| | | String name = item.toString(); |
| | | try { |
| | | // try to lookup translation |
| | | name = getString(name); |
| | | } catch (Exception e) { |
| | | } |
| | | if (item instanceof PageLinkMenuItem) { |
| | | // link to another Wicket page |
| | | PageLinkMenuItem pageLink = (PageLinkMenuItem) item; |
| | | menuItem.add(new LinkPanel("submenuLink", null, null, name, pageLink.getPageClass(), |
| | | pageLink.getPageParameters(), false).setRenderBodyOnly(true)); |
| | | } else if (item instanceof ExternalLinkMenuItem) { |
| | | // link to a specified href |
| | | ExternalLinkMenuItem extLink = (ExternalLinkMenuItem) item; |
| | | menuItem.add(new LinkPanel("submenuLink", null, name, extLink.getHref(), |
| | | extLink.openInNewWindow()).setRenderBodyOnly(true)); |
| | | } else if (item instanceof MenuDivider) { |
| | | // divider |
| | | menuItem.add(new Label("submenuLink").setRenderBodyOnly(true)); |
| | | WicketUtils.setCssClass(menuItem, "divider"); |
| | | } |
| | | } |
| | | }; |
| | | submenu.add(submenuItems); |
| | | submenu.setRenderBodyOnly(true); |
| | | return submenu; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | <!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 wicket:id="teamsPanel">[teams panel]</div>
|
| | | </div>
|
| | | </wicket:extend>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * 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.wicket.pages;
|
| | |
|
| | | import com.gitblit.wicket.RequiresAdminRole;
|
| | | import com.gitblit.wicket.panels.TeamsPanel;
|
| | |
|
| | | @RequiresAdminRole
|
| | | public class TeamsPage extends RootPage {
|
| | |
|
| | | public TeamsPage() {
|
| | | super();
|
| | | setupPage("", "");
|
| | |
|
| | | add(new TeamsPanel("teamsPanel", showAdmin).setVisible(showAdmin));
|
| | | }
|
| | | }
|
| | |
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.utils.TimeUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.TicketsUI;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.BasePanel.JavascriptTextPrompt;
|
| | | import com.gitblit.wicket.panels.CommentPanel;
|
| | |
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class TicketPage extends TicketBasePage {
|
| | | public class TicketPage extends RepositoryPage {
|
| | |
|
| | | static final String NIL = "<nil>";
|
| | |
|
| | |
| | | String href = urlFor(TicketsPage.class, params).toString();
|
| | | add(new ExternalLink("ticketNumber", href, "#" + ticket.number));
|
| | | Label headerStatus = new Label("headerStatus", ticket.status.toString());
|
| | | WicketUtils.setCssClass(headerStatus, getLozengeClass(ticket.status, false));
|
| | | WicketUtils.setCssClass(headerStatus, TicketsUI.getLozengeClass(ticket.status, false));
|
| | | add(headerStatus);
|
| | | add(new Label("ticketTitle", ticket.title));
|
| | | if (currentPatchset == null) {
|
| | |
| | | } else {
|
| | | // link to milestone query
|
| | | TicketMilestone milestone = app().tickets().getMilestone(repository, ticket.milestone);
|
| | | PageParameters milestoneParameters = new PageParameters();
|
| | | milestoneParameters.put("r", repositoryName);
|
| | | PageParameters milestoneParameters;
|
| | | if (milestone.isOpen()) {
|
| | | milestoneParameters = WicketUtils.newOpenTicketsParameter(repositoryName);
|
| | | } else {
|
| | | milestoneParameters = WicketUtils.newRepositoryParameter(repositoryName);
|
| | | }
|
| | | milestoneParameters.put(Lucene.milestone.name(), ticket.milestone);
|
| | | int progress = 0;
|
| | | int open = 0;
|
| | |
| | | if (StringUtils.isEmpty(ticket.body)) {
|
| | | desc = getString("gb.noDescriptionGiven");
|
| | | } else {
|
| | | desc = MarkdownUtils.transformGFM(app().settings(), ticket.body, ticket.repository);
|
| | | String bugtraq = bugtraqProcessor().processText(getRepository(), repositoryName, ticket.body);
|
| | | desc = MarkdownUtils.transformGFM(app().settings(), bugtraq, ticket.repository);
|
| | | }
|
| | | add(new Label("ticketDescription", desc).setEscapeModelStrings(false));
|
| | |
|
| | |
| | | * LARGE STATUS INDICATOR WITH ICON (DISCUSSION TAB->SIDE BAR)
|
| | | */
|
| | | Fragment ticketStatus = new Fragment("ticketStatus", "ticketStatusFragment", this);
|
| | | Label ticketIcon = getStateIcon("ticketIcon", ticket);
|
| | | Label ticketIcon = TicketsUI.getStateIcon("ticketIcon", ticket);
|
| | | ticketStatus.add(ticketIcon);
|
| | | ticketStatus.add(new Label("ticketStatus", ticket.status.toString()));
|
| | | WicketUtils.setCssClass(ticketStatus, getLozengeClass(ticket.status, false));
|
| | | WicketUtils.setCssClass(ticketStatus, TicketsUI.getLozengeClass(ticket.status, false));
|
| | | add(ticketStatus);
|
| | |
|
| | |
|
| | |
| | | setResponsePage(TicketsPage.class, getPageParameters());
|
| | | }
|
| | | };
|
| | | String css = getStatusClass(item.getModel().getObject());
|
| | | String css = TicketsUI.getStatusClass(item.getModel().getObject());
|
| | | WicketUtils.setCssClass(link, css);
|
| | | item.add(link);
|
| | | }
|
| | |
| | | add(new Label("ticketTopic").setVisible(false));
|
| | | } else {
|
| | | // process the topic using the bugtraq config to link things
|
| | | String topic = bugtraqProcessor().processPlainCommitMessage(getRepository(), repositoryName, ticket.topic);
|
| | | String topic = bugtraqProcessor().processText(getRepository(), repositoryName, ticket.topic);
|
| | | add(new Label("ticketTopic", topic).setEscapeModelStrings(false));
|
| | | }
|
| | |
|
| | |
| | | */
|
| | | Fragment frag = new Fragment("entry", "statusFragment", this);
|
| | | Label status = new Label("statusChange", entry.getStatus().toString());
|
| | | String css = getLozengeClass(entry.getStatus(), false);
|
| | | String css = TicketsUI.getLozengeClass(entry.getStatus(), false);
|
| | | WicketUtils.setCssClass(status, css);
|
| | | for (IBehavior b : status.getBehaviors()) {
|
| | | if (b instanceof SimpleAttributeModifier) {
|
| | |
| | | /*
|
| | | * COMMENT
|
| | | */
|
| | | String comment = MarkdownUtils.transformGFM(app().settings(), entry.comment.text, repositoryName);
|
| | | String bugtraq = bugtraqProcessor().processText(getRepository(), repositoryName, entry.comment.text);
|
| | | String comment = MarkdownUtils.transformGFM(app().settings(), bugtraq, repositoryName);
|
| | | Fragment frag = new Fragment("entry", "commentFragment", this);
|
| | | Label commentIcon = new Label("commentIcon");
|
| | | if (entry.comment.src == CommentSource.Email) {
|
| | |
| | | case status:
|
| | | // special handling for status
|
| | | Status status = event.getStatus();
|
| | | String css = getLozengeClass(status, true);
|
| | | String css = TicketsUI.getLozengeClass(status, true);
|
| | | value = String.format("<span class=\"%1$s\">%2$s</span>", css, status.toString());
|
| | | break;
|
| | | default:
|
| | |
| | | switch (type) {
|
| | | case Rebase:
|
| | | case Rebase_Squash:
|
| | | typeCss = getLozengeClass(Status.Declined, false);
|
| | | typeCss = TicketsUI.getLozengeClass(Status.Declined, false);
|
| | | break;
|
| | | case Squash:
|
| | | case Amend:
|
| | | typeCss = getLozengeClass(Status.On_Hold, false);
|
| | | typeCss = TicketsUI.getLozengeClass(Status.On_Hold, false);
|
| | | break;
|
| | | case Proposal:
|
| | | typeCss = getLozengeClass(Status.New, false);
|
| | | typeCss = TicketsUI.getLozengeClass(Status.New, false);
|
| | | break;
|
| | | case FastForward:
|
| | | default:
|
| | |
| | | <div class="hidden-phone pull-right">
|
| | | <form class="form-search" style="margin: 0px;" wicket:id="ticketSearchForm">
|
| | | <div class="input-append">
|
| | | <input type="text" class="search-query" style="width: 170px;border-radius: 14px 0 0 14px; padding-left: 14px;" id="ticketSearchBox" wicket:id="ticketSearchBox" value=""/>
|
| | | <input type="text" class="input-medium search-query" style="border-radius: 14px 0 0 14px; padding-left: 14px;" id="ticketSearchBox" wicket:id="ticketSearchBox" value=""/>
|
| | | <button class="btn" style="border-radius: 0 14px 14px 0px;margin-left:-5px;" type="submit"><i class="icon-search"></i></button>
|
| | | </div>
|
| | | </form>
|
| | |
| | | </div>
|
| | | </div>
|
| | |
|
| | | |
| | | <table class="table tickets"> |
| | | <tbody>
|
| | | <tr wicket:id="ticket">
|
| | | <td class="ticket-list-icon">
|
| | | <i wicket:id="state"></i>
|
| | | </td>
|
| | | <td>
|
| | | <span wicket:id="title">[title]</span> <span wicket:id="labels" style="font-weight: normal;color:white;"><span class="label" wicket:id="label"></span></span>
|
| | | <div class="ticket-list-details">
|
| | | <span style="padding-right: 10px;" class="hidden-phone">
|
| | | <wicket:message key="gb.createdBy"></wicket:message>
|
| | | <span style="padding: 0px 2px" wicket:id="createdBy">[createdBy]</span> <span class="date" wicket:id="createDate">[create date]</span>
|
| | | </span>
|
| | | <span wicket:id="indicators" style="white-space:nowrap;"><i wicket:id="icon"></i> <span style="padding-right:10px;" wicket:id="count"></span></span>
|
| | | </div>
|
| | | <div class="hidden-phone" wicket:id="updated"></div>
|
| | | </td>
|
| | | <td class="ticket-list-state">
|
| | | <span class="badge badge-info" wicket:id="votes"></span>
|
| | | </td>
|
| | | <td class="hidden-phone ticket-list-state">
|
| | | <i wicket:message="title:gb.watching" style="color:#888;" class="fa fa-eye" wicket:id="watching"></i>
|
| | | </td>
|
| | | <td class="ticket-list-state">
|
| | | <div wicket:id="status"></div>
|
| | | </td>
|
| | | <td class="indicators">
|
| | | <div> |
| | | <b>#<span wicket:id="id">[id]</span></b>
|
| | | </div>
|
| | | <div wicket:id="responsible"></div>
|
| | | </td>
|
| | | </tr>
|
| | | </tbody>
|
| | | </table>
|
| | | <div wicket:id="ticketList"></div>
|
| | |
|
| | | <div class="btn-group pull-right">
|
| | | <div class="pagination pagination-right pagination-small">
|
| | |
| | | </div>
|
| | | <div class="tab-pane" id="milestones">
|
| | | <div class="row">
|
| | | <div class="span9" wicket:id="milestoneList" style="padding-bottom: 10px;">
|
| | | <h3><span wicket:id="milestoneName"></span> <small><span wicket:id="milestoneState"></span></small></h3>
|
| | | <i style="color:#888;"class="fa fa-calendar"></i> <span wicket:id="milestoneDue"></span>
|
| | | <span class="span12" style="padding-bottom:10px;" wicket:id="newMilestone"></span>
|
| | | </div>
|
| | |
|
| | | <div class="row">
|
| | | <div class="span12"><h2><wicket:message key="gb.openMilestones"></wicket:message></h2></div>
|
| | | <div class="span12"><hr/></div>
|
| | | </div> |
| | | <div class="row">
|
| | | <div class="span4" wicket:id="openMilestonesList" style="padding-bottom: 20px;">
|
| | | <div wicket:id="entryPanel"></div>
|
| | | </div>
|
| | | </div>
|
| | |
|
| | | <div class="row">
|
| | | <div class="span12"><h2><wicket:message key="gb.closedMilestones"></wicket:message></h2></div>
|
| | | <div class="span12"><hr/></div>
|
| | | </div> |
| | | <div class="row">
|
| | | <div class="span3" wicket:id="closedMilestonesList" style="padding-bottom: 15px;">
|
| | | <div wicket:id="entryPanel"></div>
|
| | | </div>
|
| | | </div>
|
| | | |
| | | </div>
|
| | | </div>
|
| | |
|
| | | <wicket:fragment wicket:id="milestoneListFragment">
|
| | | <h3><span wicket:id="milestoneName"></span> <small><span wicket:id="milestoneState"></span></small></h3>
|
| | | <i style="color:#888;"class="fa fa-calendar"></i> <span wicket:id="milestoneDue"></span> <span wicket:id="editMilestone"></span>
|
| | | <div wicket:id="milestonePanel"></div>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="openMilestoneFragment">
|
| | | <div style="clear:both;padding-bottom: 10px;">
|
| | | <div style="margin-bottom: 5px;" class="progress progress-success">
|
| | | <div class="bar" wicket:id="progress"></div>
|
| | | </div>
|
| | | <div class="milestoneOverview">
|
| | | <span wicket:id="openTickets" />,
|
| | | <span wicket:id="closedTickets" />,
|
| | | <span wicket:id="totalTickets" />
|
| | | </div>
|
| | | </div>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="noMilestoneFragment">
|
| | | <table style="width: 100%;padding-bottom: 5px;">
|
| | |
| | | <li class="nav-header"><wicket:message key="gb.topicsAndLabels"></wicket:message></li>
|
| | | <li class="dynamicQuery" wicket:id="dynamicQuery"><span><span wicket:id="swatch"></span> <span wicket:id="link"></span></span><span class="pull-right"><i style="font-size: 18px;" wicket:id="checked"></i></span></li>
|
| | | </ul>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="updatedFragment">
|
| | | <div class="ticket-list-details">
|
| | | <wicket:message key="gb.updatedBy"></wicket:message>
|
| | | <span style="padding: 0px 2px" wicket:id="updatedBy">[updatedBy]</span> <span class="date" wicket:id="updateDate">[update date]</span>
|
| | | </div>
|
| | | </wicket:fragment>
|
| | |
|
| | | </wicket:extend>
|
| | |
| | | */
|
| | | package com.gitblit.wicket.pages;
|
| | |
|
| | | import java.io.Serializable;
|
| | | import java.text.MessageFormat;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Arrays;
|
| | | import java.util.Collections;
|
| | | import java.util.Comparator;
|
| | | import java.util.List;
|
| | | import java.util.Set;
|
| | | import java.util.TreeSet;
|
| | |
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.behavior.SimpleAttributeModifier;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.apache.wicket.markup.repeater.Item;
|
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | | import org.apache.wicket.request.target.basic.RedirectRequestTarget;
|
| | |
|
| | | import com.gitblit.Constants;
|
| | | import com.gitblit.Constants.AccessPermission;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.RegistrantAccessPermission;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.TicketModel;
|
| | | import com.gitblit.models.TicketModel.Status;
|
| | | import com.gitblit.models.UserModel;
|
| | |
| | | import com.gitblit.utils.ArrayUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.SessionlessForm;
|
| | | import com.gitblit.wicket.TicketsUI;
|
| | | import com.gitblit.wicket.TicketsUI.TicketQuery;
|
| | | import com.gitblit.wicket.TicketsUI.TicketSort;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.GravatarImage;
|
| | | import com.gitblit.wicket.panels.LinkPanel;
|
| | | import com.gitblit.wicket.panels.TicketListPanel;
|
| | | import com.gitblit.wicket.panels.TicketSearchForm;
|
| | |
|
| | | public class TicketsPage extends TicketBasePage {
|
| | | public class TicketsPage extends RepositoryPage {
|
| | |
|
| | | final TicketResponsible any;
|
| | |
|
| | | public static final String [] openStatii = new String [] { Status.New.name().toLowerCase(), Status.Open.name().toLowerCase() };
|
| | |
|
| | | public static final String [] closedStatii = new String [] { "!" + Status.New.name().toLowerCase(), "!" + Status.Open.name().toLowerCase() };
|
| | |
|
| | | public TicketsPage(PageParameters params) {
|
| | | super(params);
|
| | |
| | | final String sortBy = Lucene.fromString(params.getString("sort", Lucene.created.name())).name();
|
| | | final boolean desc = !"asc".equals(params.getString("direction", "desc"));
|
| | |
|
| | |
|
| | | // add search form
|
| | | TicketSearchForm searchForm = new TicketSearchForm("ticketSearchForm", repositoryName, searchParam);
|
| | | add(searchForm);
|
| | | searchForm.setTranslatedAttributes();
|
| | | add(new TicketSearchForm("ticketSearchForm", repositoryName, searchParam, getClass(), params));
|
| | |
|
| | | final String activeQuery;
|
| | | if (!StringUtils.isEmpty(searchParam)) {
|
| | |
| | | milestonePanel.add(new LinkPanel("openTickets", null,
|
| | | MessageFormat.format(getString("gb.nOpenTickets"), currentMilestone.getOpenTickets()),
|
| | | TicketsPage.class,
|
| | | queryParameters(null, currentMilestone.name, openStatii, null, sortBy, desc, 1)));
|
| | | queryParameters(null, currentMilestone.name, TicketsUI.openStatii, null, sortBy, desc, 1)));
|
| | |
|
| | | milestonePanel.add(new LinkPanel("closedTickets", null,
|
| | | MessageFormat.format(getString("gb.nClosedTickets"), currentMilestone.getClosedTickets()),
|
| | | TicketsPage.class,
|
| | | queryParameters(null, currentMilestone.name, closedStatii, null, sortBy, desc, 1)));
|
| | | queryParameters(null, currentMilestone.name, TicketsUI.closedStatii, null, sortBy, desc, 1)));
|
| | |
|
| | | milestonePanel.add(new Label("totalTickets", MessageFormat.format(getString("gb.nTotalTickets"), currentMilestone.getTotalTickets())));
|
| | | add(milestonePanel);
|
| | |
| | | queryParameters(
|
| | | null,
|
| | | milestoneParam,
|
| | | openStatii,
|
| | | TicketsUI.openStatii,
|
| | | null,
|
| | | null,
|
| | | true,
|
| | |
| | | } else {
|
| | | add(new Label("selectedStatii", StringUtils.flattenStrings(Arrays.asList(statiiParam), ",")));
|
| | | }
|
| | | add(new BookmarkablePageLink<Void>("openTickets", TicketsPage.class, queryParameters(queryParam, milestoneParam, openStatii, assignedToParam, sortBy, desc, 1)));
|
| | | add(new BookmarkablePageLink<Void>("closedTickets", TicketsPage.class, queryParameters(queryParam, milestoneParam, closedStatii, assignedToParam, sortBy, desc, 1)));
|
| | | add(new BookmarkablePageLink<Void>("openTickets", TicketsPage.class, queryParameters(queryParam, milestoneParam, TicketsUI.openStatii, assignedToParam, sortBy, desc, 1)));
|
| | | add(new BookmarkablePageLink<Void>("closedTickets", TicketsPage.class, queryParameters(queryParam, milestoneParam, TicketsUI.closedStatii, assignedToParam, sortBy, desc, 1)));
|
| | | add(new BookmarkablePageLink<Void>("allTickets", TicketsPage.class, queryParameters(queryParam, milestoneParam, null, assignedToParam, sortBy, desc, 1)));
|
| | |
|
| | | // by status
|
| | |
| | | public void populateItem(final Item<Status> item) {
|
| | | final Status status = item.getModelObject();
|
| | | PageParameters p = queryParameters(queryParam, milestoneParam, new String [] { status.name().toLowerCase() }, assignedToParam, sortBy, desc, 1);
|
| | | String css = getStatusClass(status);
|
| | | String css = TicketsUI.getStatusClass(status);
|
| | | item.add(new LinkPanel("statusLink", css, status.toString(), TicketsPage.class, p).setRenderBodyOnly(true));
|
| | | }
|
| | | };
|
| | |
| | | // paging links
|
| | | buildPager(queryParam, milestoneParam, statiiParam, assignedToParam, sortBy, desc, page, pageSize, results.size(), totalResults);
|
| | |
|
| | | ListDataProvider<QueryResult> resultsDataProvider = new ListDataProvider<QueryResult>(results);
|
| | | DataView<QueryResult> ticketsView = new DataView<QueryResult>("ticket", resultsDataProvider) {
|
| | | private static final long serialVersionUID = 1L;
|
| | | add(new TicketListPanel("ticketList", results, false, false));
|
| | |
|
| | | @Override
|
| | | public void populateItem(final Item<QueryResult> item) {
|
| | | final QueryResult ticket = item.getModelObject();
|
| | | item.add(getStateIcon("state", ticket.type, ticket.status));
|
| | | item.add(new Label("id", "" + ticket.number));
|
| | | UserModel creator = app().users().getUserModel(ticket.createdBy);
|
| | | if (creator != null) {
|
| | | item.add(new LinkPanel("createdBy", null, creator.getDisplayName(),
|
| | | UserPage.class, WicketUtils.newUsernameParameter(ticket.createdBy)));
|
| | | } else {
|
| | | item.add(new Label("createdBy", ticket.createdBy));
|
| | | }
|
| | | item.add(WicketUtils.createDateLabel("createDate", ticket.createdAt, GitBlitWebSession
|
| | | .get().getTimezone(), getTimeUtils(), false));
|
| | | // new milestone link
|
| | | RepositoryModel repositoryModel = getRepositoryModel();
|
| | | final boolean acceptingUpdates = app().tickets().isAcceptingTicketUpdates(repositoryModel)
|
| | | && user != null && user.canAdmin(getRepositoryModel());
|
| | | if (acceptingUpdates) {
|
| | | add(new LinkPanel("newMilestone", null, getString("gb.newMilestone"),
|
| | | NewMilestonePage.class, WicketUtils.newRepositoryParameter(repositoryName)));
|
| | | } else {
|
| | | add(new Label("newMilestone").setVisible(false));
|
| | | }
|
| | |
|
| | | if (ticket.updatedAt == null) {
|
| | | item.add(new Label("updated").setVisible(false));
|
| | | } else {
|
| | | Fragment updated = new Fragment("updated", "updatedFragment", this);
|
| | | UserModel updater = app().users().getUserModel(ticket.updatedBy);
|
| | | if (updater != null) {
|
| | | updated.add(new LinkPanel("updatedBy", null, updater.getDisplayName(),
|
| | | UserPage.class, WicketUtils.newUsernameParameter(ticket.updatedBy)));
|
| | | } else {
|
| | | updated.add(new Label("updatedBy", ticket.updatedBy));
|
| | | }
|
| | | updated.add(WicketUtils.createDateLabel("updateDate", ticket.updatedAt, GitBlitWebSession
|
| | | .get().getTimezone(), getTimeUtils(), false));
|
| | | item.add(updated);
|
| | | }
|
| | |
|
| | | item.add(new LinkPanel("title", "list subject", StringUtils.trimString(
|
| | | ticket.title, Constants.LEN_SHORTLOG), TicketsPage.class, newTicketParameter(ticket)));
|
| | |
|
| | | ListDataProvider<String> labelsProvider = new ListDataProvider<String>(ticket.getLabels());
|
| | | DataView<String> labelsView = new DataView<String>("labels", labelsProvider) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void populateItem(final Item<String> labelItem) {
|
| | | String content = bugtraqProcessor().processPlainCommitMessage(getRepository(), repositoryName, labelItem.getModelObject());
|
| | | Label label = new Label("label", content);
|
| | | label.setEscapeModelStrings(false);
|
| | | TicketLabel tLabel = app().tickets().getLabel(getRepositoryModel(), labelItem.getModelObject());
|
| | | String background = MessageFormat.format("background-color:{0};", tLabel.color);
|
| | | label.add(new SimpleAttributeModifier("style", background));
|
| | | labelItem.add(label);
|
| | | }
|
| | | };
|
| | | item.add(labelsView);
|
| | |
|
| | | if (StringUtils.isEmpty(ticket.responsible)) {
|
| | | item.add(new Label("responsible").setVisible(false));
|
| | | } else {
|
| | | UserModel responsible = app().users().getUserModel(ticket.responsible);
|
| | | if (responsible == null) {
|
| | | responsible = new UserModel(ticket.responsible);
|
| | | }
|
| | | GravatarImage avatar = new GravatarImage("responsible", responsible.getDisplayName(),
|
| | | responsible.emailAddress, null, 16, true);
|
| | | avatar.setTooltip(getString("gb.responsible") + ": " + responsible.getDisplayName());
|
| | | item.add(avatar);
|
| | | }
|
| | |
|
| | | // votes indicator
|
| | | Label v = new Label("votes", "" + ticket.votesCount);
|
| | | WicketUtils.setHtmlTooltip(v, getString("gb.votes"));
|
| | | item.add(v.setVisible(ticket.votesCount > 0));
|
| | |
|
| | | // watching indicator
|
| | | item.add(new Label("watching").setVisible(ticket.isWatching(GitBlitWebSession.get().getUsername())));
|
| | |
|
| | | // status indicator
|
| | | String css = getLozengeClass(ticket.status, true);
|
| | | Label l = new Label("status", ticket.status.toString());
|
| | | WicketUtils.setCssClass(l, css);
|
| | | item.add(l);
|
| | |
|
| | | // add the ticket indicators/icons
|
| | | List<Indicator> indicators = new ArrayList<Indicator>();
|
| | |
|
| | | // comments
|
| | | if (ticket.commentsCount > 0) {
|
| | | int count = ticket.commentsCount;
|
| | | String pattern = "gb.nComments";
|
| | | if (count == 1) {
|
| | | pattern = "gb.oneComment";
|
| | | }
|
| | | indicators.add(new Indicator("fa fa-comment", count, pattern));
|
| | | }
|
| | |
|
| | | // participants
|
| | | if (!ArrayUtils.isEmpty(ticket.participants)) {
|
| | | int count = ticket.participants.size();
|
| | | if (count > 1) {
|
| | | String pattern = "gb.nParticipants";
|
| | | indicators.add(new Indicator("fa fa-user", count, pattern));
|
| | | }
|
| | | }
|
| | |
|
| | | // attachments
|
| | | if (!ArrayUtils.isEmpty(ticket.attachments)) {
|
| | | int count = ticket.attachments.size();
|
| | | String pattern = "gb.nAttachments";
|
| | | if (count == 1) {
|
| | | pattern = "gb.oneAttachment";
|
| | | }
|
| | | indicators.add(new Indicator("fa fa-file", count, pattern));
|
| | | }
|
| | |
|
| | | // patchset revisions
|
| | | if (ticket.patchset != null) {
|
| | | int count = ticket.patchset.commits;
|
| | | String pattern = "gb.nCommits";
|
| | | if (count == 1) {
|
| | | pattern = "gb.oneCommit";
|
| | | }
|
| | | indicators.add(new Indicator("fa fa-code", count, pattern));
|
| | | }
|
| | |
|
| | | // milestone
|
| | | if (!StringUtils.isEmpty(ticket.milestone)) {
|
| | | indicators.add(new Indicator("fa fa-bullseye", ticket.milestone));
|
| | | }
|
| | |
|
| | | ListDataProvider<Indicator> indicatorsDp = new ListDataProvider<Indicator>(indicators);
|
| | | DataView<Indicator> indicatorsView = new DataView<Indicator>("indicators", indicatorsDp) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void populateItem(final Item<Indicator> item) {
|
| | | Indicator indicator = item.getModelObject();
|
| | | String tooltip = indicator.getTooltip();
|
| | |
|
| | | Label icon = new Label("icon");
|
| | | WicketUtils.setCssClass(icon, indicator.css);
|
| | | item.add(icon);
|
| | |
|
| | | if (indicator.count > 0) {
|
| | | Label count = new Label("count", "" + indicator.count);
|
| | | item.add(count.setVisible(!StringUtils.isEmpty(tooltip)));
|
| | | } else {
|
| | | item.add(new Label("count").setVisible(false));
|
| | | }
|
| | |
|
| | | WicketUtils.setHtmlTooltip(item, tooltip);
|
| | | }
|
| | | };
|
| | | item.add(indicatorsView);
|
| | | // milestones list
|
| | | List<TicketMilestone> openMilestones = new ArrayList<TicketMilestone>();
|
| | | List<TicketMilestone> closedMilestones = new ArrayList<TicketMilestone>();
|
| | | for (TicketMilestone milestone : app().tickets().getMilestones(repositoryModel)) {
|
| | | if (milestone.isOpen()) {
|
| | | openMilestones.add(milestone);
|
| | | } else {
|
| | | closedMilestones.add(milestone);
|
| | | }
|
| | | };
|
| | | add(ticketsView);
|
| | | }
|
| | | Collections.sort(openMilestones, new Comparator<TicketMilestone>() {
|
| | | @Override
|
| | | public int compare(TicketMilestone o1, TicketMilestone o2) {
|
| | | return o2.due.compareTo(o1.due);
|
| | | }
|
| | | });
|
| | |
|
| | | List<TicketMilestone> allMilestones = app().tickets().getMilestones(getRepositoryModel());
|
| | | ListDataProvider<TicketMilestone> allMilestonesDp = new ListDataProvider<TicketMilestone>(allMilestones);
|
| | | DataView<TicketMilestone> milestonesList = new DataView<TicketMilestone>("milestoneList", allMilestonesDp) {
|
| | | Collections.sort(closedMilestones, new Comparator<TicketMilestone>() {
|
| | | @Override
|
| | | public int compare(TicketMilestone o1, TicketMilestone o2) {
|
| | | return o2.due.compareTo(o1.due);
|
| | | }
|
| | | });
|
| | |
|
| | | DataView<TicketMilestone> openMilestonesList = milestoneList("openMilestonesList", openMilestones, acceptingUpdates);
|
| | | add(openMilestonesList);
|
| | |
|
| | | DataView<TicketMilestone> closedMilestonesList = milestoneList("closedMilestonesList", closedMilestones, acceptingUpdates);
|
| | | add(closedMilestonesList);
|
| | | }
|
| | |
|
| | | protected DataView<TicketMilestone> milestoneList(String wicketId, List<TicketMilestone> milestones, final boolean acceptingUpdates) {
|
| | | ListDataProvider<TicketMilestone> milestonesDp = new ListDataProvider<TicketMilestone>(milestones);
|
| | | DataView<TicketMilestone> milestonesList = new DataView<TicketMilestone>(wicketId, milestonesDp) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void populateItem(final Item<TicketMilestone> item) {
|
| | | Fragment entryPanel = new Fragment("entryPanel", "milestoneListFragment", this);
|
| | | item.add(entryPanel);
|
| | |
|
| | | final TicketMilestone tm = item.getModelObject();
|
| | | PageParameters params = queryParameters(null, tm.name, null, null, null, desc, 1);
|
| | | item.add(new LinkPanel("milestoneName", null, tm.name, TicketsPage.class, params).setRenderBodyOnly(true));
|
| | | String [] states;
|
| | | if (tm.isOpen()) {
|
| | | states = TicketsUI.openStatii;
|
| | | } else {
|
| | | states = TicketsUI.closedStatii;
|
| | | }
|
| | | PageParameters params = queryParameters(null, tm.name, states, null, null, true, 1);
|
| | | entryPanel.add(new LinkPanel("milestoneName", null, tm.name, TicketsPage.class, params).setRenderBodyOnly(true));
|
| | |
|
| | | String css;
|
| | | String status = tm.status.name();
|
| | | switch (tm.status) {
|
| | | case Open:
|
| | | css = "aui-lozenge aui-lozenge-subtle";
|
| | | if (tm.isOverdue()) {
|
| | | css = "aui-lozenge aui-lozenge-subtle aui-lozenge-error";
|
| | | status = "overdue";
|
| | | } else {
|
| | | css = "aui-lozenge aui-lozenge-subtle";
|
| | | }
|
| | | break;
|
| | | default:
|
| | | css = "aui-lozenge";
|
| | | break;
|
| | | }
|
| | | Label stateLabel = new Label("milestoneState", tm.status.name());
|
| | | Label stateLabel = new Label("milestoneState", status);
|
| | | WicketUtils.setCssClass(stateLabel, css);
|
| | | item.add(stateLabel);
|
| | | entryPanel.add(stateLabel);
|
| | |
|
| | | if (tm.due == null) {
|
| | | item.add(new Label("milestoneDue", getString("gb.notSpecified")));
|
| | | entryPanel.add(new Label("milestoneDue", getString("gb.notSpecified")));
|
| | | } else {
|
| | | item.add(WicketUtils.createDatestampLabel("milestoneDue", tm.due, getTimeZone(), getTimeUtils()));
|
| | | entryPanel.add(WicketUtils.createDatestampLabel("milestoneDue", tm.due, getTimeZone(), getTimeUtils()));
|
| | | }
|
| | | if (acceptingUpdates) {
|
| | | entryPanel.add(new LinkPanel("editMilestone", null, getString("gb.edit"), EditMilestonePage.class,
|
| | | WicketUtils.newObjectParameter(repositoryName, tm.name)));
|
| | | } else {
|
| | | entryPanel.add(new Label("editMilestone").setVisible(false));
|
| | | }
|
| | |
|
| | | if (tm.isOpen()) {
|
| | | // re-load milestone with query results
|
| | | TicketMilestone m = app().tickets().getMilestone(getRepositoryModel(), tm.name);
|
| | |
|
| | | Fragment milestonePanel = new Fragment("milestonePanel", "openMilestoneFragment", this);
|
| | | Label label = new Label("progress");
|
| | | WicketUtils.setCssStyle(label, "width:" + m.getProgress() + "%;");
|
| | | milestonePanel.add(label);
|
| | |
|
| | | milestonePanel.add(new LinkPanel("openTickets", null,
|
| | | MessageFormat.format(getString("gb.nOpenTickets"), m.getOpenTickets()),
|
| | | TicketsPage.class,
|
| | | queryParameters(null, tm.name, TicketsUI.openStatii, null, null, true, 1)));
|
| | |
|
| | | milestonePanel.add(new LinkPanel("closedTickets", null,
|
| | | MessageFormat.format(getString("gb.nClosedTickets"), m.getClosedTickets()),
|
| | | TicketsPage.class,
|
| | | queryParameters(null, tm.name, TicketsUI.closedStatii, null, null, true, 1)));
|
| | |
|
| | | milestonePanel.add(new Label("totalTickets", MessageFormat.format(getString("gb.nTotalTickets"), m.getTotalTickets())));
|
| | | entryPanel.add(milestonePanel);
|
| | | } else {
|
| | | entryPanel.add(new Label("milestonePanel").setVisible(false));
|
| | | }
|
| | | }
|
| | | };
|
| | | add(milestonesList);
|
| | | return milestonesList;
|
| | | }
|
| | |
|
| | | protected PageParameters queryParameters(
|
| | |
| | | }
|
| | | };
|
| | | add(pagesView);
|
| | | }
|
| | |
|
| | | private class Indicator implements Serializable {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | final String css;
|
| | | final int count;
|
| | | final String tooltip;
|
| | |
|
| | | Indicator(String css, String tooltip) {
|
| | | this.css = css;
|
| | | this.tooltip = tooltip;
|
| | | this.count = 0;
|
| | | }
|
| | |
|
| | | Indicator(String css, int count, String pattern) {
|
| | | this.css = css;
|
| | | this.count = count;
|
| | | this.tooltip = StringUtils.isEmpty(pattern) ? "" : MessageFormat.format(getString(pattern), count);
|
| | | }
|
| | |
|
| | | String getTooltip() {
|
| | | return tooltip;
|
| | | }
|
| | | }
|
| | |
|
| | | private class TicketQuery implements Serializable, Comparable<TicketQuery> {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | final String name;
|
| | | final String query;
|
| | | String color;
|
| | |
|
| | | TicketQuery(String name, String query) {
|
| | | this.name = name;
|
| | | this.query = query;
|
| | | }
|
| | |
|
| | | TicketQuery color(String value) {
|
| | | this.color = value;
|
| | | return this;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean equals(Object o) {
|
| | | if (o instanceof TicketQuery) {
|
| | | return ((TicketQuery) o).query.equals(query);
|
| | | }
|
| | | return false;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public int hashCode() {
|
| | | return query.hashCode();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public int compareTo(TicketQuery o) {
|
| | | return query.compareTo(o.query);
|
| | | }
|
| | | }
|
| | |
|
| | | private class TicketSort implements Serializable {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | final String name;
|
| | | final String sortBy;
|
| | | final boolean desc;
|
| | |
|
| | | TicketSort(String name, String sortBy, boolean desc) {
|
| | | this.name = name;
|
| | | this.sortBy = sortBy;
|
| | | this.desc = desc;
|
| | | }
|
| | | }
|
| | |
|
| | | private class TicketSearchForm extends SessionlessForm<Void> implements Serializable {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | private final String repositoryName;
|
| | |
|
| | | private final IModel<String> searchBoxModel;;
|
| | |
|
| | | public TicketSearchForm(String id, String repositoryName, String text) {
|
| | | super(id, TicketsPage.this.getClass(), TicketsPage.this.getPageParameters());
|
| | |
|
| | | this.repositoryName = repositoryName;
|
| | | this.searchBoxModel = new Model<String>(text == null ? "" : text);
|
| | |
|
| | | TextField<String> searchBox = new TextField<String>("ticketSearchBox", searchBoxModel);
|
| | | add(searchBox);
|
| | | }
|
| | |
|
| | | void setTranslatedAttributes() {
|
| | | WicketUtils.setHtmlTooltip(get("ticketSearchBox"),
|
| | | MessageFormat.format(getString("gb.searchTicketsTooltip"), repositoryName));
|
| | | WicketUtils.setInputPlaceholder(get("ticketSearchBox"), getString("gb.searchTickets"));
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void onSubmit() {
|
| | | String searchString = searchBoxModel.getObject();
|
| | | if (StringUtils.isEmpty(searchString)) {
|
| | | // redirect to self to avoid wicket page update bug
|
| | | String absoluteUrl = getCanonicalUrl();
|
| | | getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
|
| | | return;
|
| | | }
|
| | |
|
| | | // use an absolute url to workaround Wicket-Tomcat problems with
|
| | | // mounted url parameters (issue-111)
|
| | | PageParameters params = WicketUtils.newRepositoryParameter(repositoryName);
|
| | | params.add("s", searchString);
|
| | | String absoluteUrl = getCanonicalUrl(TicketsPage.class, params);
|
| | | getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
|
| | | }
|
| | | }
|
| | | }
|
| | |
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.apache.wicket.markup.repeater.Item;
|
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | |
| | |
|
| | | import com.gitblit.models.PathModel;
|
| | | import com.gitblit.models.SubmoduleModel;
|
| | | import com.gitblit.servlet.RawServlet;
|
| | | import com.gitblit.utils.ByteFormat;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.wicket.CacheControl;
|
| | |
| | | links.add(new BookmarkablePageLink<Void>("view", BlobPage.class,
|
| | | WicketUtils.newPathParameter(repositoryName, id,
|
| | | path)));
|
| | | links.add(new BookmarkablePageLink<Void>("raw", RawPage.class, WicketUtils
|
| | | .newPathParameter(repositoryName, id, path)));
|
| | | String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, id, path);
|
| | | links.add(new ExternalLink("raw", rawUrl));
|
| | | links.add(new BookmarkablePageLink<Void>("blame", BlamePage.class,
|
| | | WicketUtils.newPathParameter(repositoryName, id,
|
| | | path)));
|
| | |
| | | <body>
|
| | | <wicket:extend>
|
| | | <div class="container">
|
| | | <div class="row" style="padding-top:10px;">
|
| | | <div class="span4">
|
| | | <div wicket:id="gravatar"></div>
|
| | | <div style="text-align: left;">
|
| | | <h2><span wicket:id="userDisplayName"></span></h2>
|
| | | <div><i class="icon-user"></i> <span wicket:id="userUsername"></span></div>
|
| | | <div><i class="icon-envelope"></i><span wicket:id="userEmail"></span></div>
|
| | | </div>
|
| | | <div class="row" style="padding-top:15px;">
|
| | | <div class="span3">
|
| | | <div wicket:id="userTitlePanel"></div>
|
| | | </div>
|
| | | |
| | | <div class="span8">
|
| | | <div class="pull-right">
|
| | | <a class="btn-small" wicket:id="newRepository" style="padding-right:0px;">
|
| | | <i class="icon icon-plus-sign"></i>
|
| | | <wicket:message key="gb.newRepository"></wicket:message>
|
| | | </a>
|
| | | </div>
|
| | | <div class="tabbable">
|
| | | </div>
|
| | | |
| | | <div class="row" style="padding-top:10px;"> |
| | | <div class="span12">
|
| | | <div class="tabbable tabs-left">
|
| | | <!-- tab titles -->
|
| | | <ul class="nav nav-tabs">
|
| | | <li class="active"><a href="#repositories" data-toggle="tab"><wicket:message key="gb.repositories"></wicket:message></a></li>
|
| | | <div wicket:id="preferencesLink"></div>
|
| | | <div wicket:id="sshKeysLink"></div>
|
| | | </ul>
|
| | |
|
| | | <!-- tab content -->
|
| | |
| | | </tbody>
|
| | | </table>
|
| | | </div>
|
| | | |
| | | <!-- preferences tab -->
|
| | | <div wicket:id="preferencesTab"></div>
|
| | | |
| | | <!-- ssh keys tab -->
|
| | | <div wicket:id="sshKeysTab"></div>
|
| | | |
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | |
|
| | | <wicket:fragment wicket:id="preferencesLinkFragment">
|
| | | <li><a href="#preferences" data-toggle="tab"><wicket:message key="gb.preferences"></wicket:message></a></li>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="sshKeysLinkFragment">
|
| | | <li><a href="#ssh" data-toggle="tab"><wicket:message key="gb.sshKeys"></wicket:message></a></li>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="preferencesTabFragment">
|
| | | <div class="tab-pane" id="preferences">
|
| | | <h4><wicket:message key="gb.accountPreferences"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.accountPreferencesDescription"></wicket:message></p>
|
| | | <hr />
|
| | | |
| | | <form wicket:id="prefsForm">
|
| | | <div wicket:id="displayName"></div>
|
| | | <div wicket:id="emailAddress"></div>
|
| | | <div wicket:id="emailMeOnMyTicketChanges"></div>
|
| | | <div wicket:id="language"></div>
|
| | | <div wicket:id="transport"></div>
|
| | | |
| | | <div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" /></div>
|
| | | </form> |
| | | </div>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="sshKeysTabFragment">
|
| | | <div class="tab-pane" id="ssh">
|
| | | <div wicket:id="sshKeysPanel"></div> |
| | | </div>
|
| | | </wicket:fragment>
|
| | |
|
| | | </wicket:extend>
|
| | | </body>
|
| | | </html> |
| | |
| | | */
|
| | | package com.gitblit.wicket.pages;
|
| | |
|
| | | import java.io.Serializable;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Arrays;
|
| | | import java.util.Collections;
|
| | | import java.util.Comparator;
|
| | | import java.util.List;
|
| | | import java.util.Locale;
|
| | |
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.ajax.AjaxRequestTarget;
|
| | | import org.apache.wicket.ajax.markup.html.form.AjaxButton;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.form.Form;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.apache.wicket.markup.repeater.Item;
|
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
| | | import org.eclipse.jgit.lib.PersonIdent;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | |
|
| | | import com.gitblit.Constants.Transport;
|
| | | import com.gitblit.GitBlitException;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.Menu.ParameterMenuItem;
|
| | | import com.gitblit.models.NavLink;
|
| | | import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
|
| | | import com.gitblit.models.ProjectModel;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | |
| | | import com.gitblit.wicket.GitBlitWebApp;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.GitblitRedirectException;
|
| | | import com.gitblit.wicket.PageRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.GravatarImage;
|
| | | import com.gitblit.wicket.panels.LinkPanel;
|
| | | import com.gitblit.wicket.panels.BooleanOption;
|
| | | import com.gitblit.wicket.panels.ChoiceOption;
|
| | | import com.gitblit.wicket.panels.ProjectRepositoryPanel;
|
| | | import com.gitblit.wicket.panels.SshKeysPanel;
|
| | | import com.gitblit.wicket.panels.TextOption;
|
| | | import com.gitblit.wicket.panels.UserTitlePanel;
|
| | |
|
| | | public class UserPage extends RootPage {
|
| | |
|
| | |
| | | user = new UserModel(userName);
|
| | | }
|
| | |
|
| | | add(new Label("userDisplayName", user.getDisplayName()));
|
| | | add(new Label("userUsername", user.username));
|
| | | LinkPanel email = new LinkPanel("userEmail", null, user.emailAddress, "mailto:#");
|
| | | email.setRenderBodyOnly(true);
|
| | | add(email.setVisible(app().settings().getBoolean(Keys.web.showEmailAddresses, true) && !StringUtils.isEmpty(user.emailAddress)));
|
| | |
|
| | | PersonIdent person = new PersonIdent(user.getDisplayName(), user.emailAddress == null ? user.getDisplayName() : user.emailAddress);
|
| | | add(new GravatarImage("gravatar", person, 210));
|
| | | add(new UserTitlePanel("userTitlePanel", user, user.username));
|
| | |
|
| | | UserModel sessionUser = GitBlitWebSession.get().getUser();
|
| | | if (sessionUser != null && user.canCreate() && sessionUser.equals(user)) {
|
| | | // user can create personal repositories
|
| | | add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
|
| | | boolean isMyProfile = sessionUser != null && sessionUser.equals(user);
|
| | |
|
| | | if (isMyProfile) {
|
| | | addPreferences(user);
|
| | |
|
| | | if (app().gitblit().isServingSSH()) {
|
| | | // show the SSH key management tab
|
| | | addSshKeys(user);
|
| | | } else {
|
| | | // SSH daemon is disabled, hide keys tab
|
| | | add(new Label("sshKeysLink").setVisible(false));
|
| | | add(new Label("sshKeysTab").setVisible(false));
|
| | | }
|
| | | } else {
|
| | | add(new Label("newRepository").setVisible(false));
|
| | | // visiting user
|
| | | add(new Label("preferencesLink").setVisible(false));
|
| | | add(new Label("preferencesTab").setVisible(false));
|
| | |
|
| | | add(new Label("sshKeysLink").setVisible(false));
|
| | | add(new Label("sshKeysTab").setVisible(false));
|
| | | }
|
| | |
|
| | | List<RepositoryModel> repositories = getRepositories(params);
|
| | |
| | | }
|
| | |
|
| | | @Override
|
| | | protected void addDropDownMenus(List<PageRegistration> pages) {
|
| | | protected void addDropDownMenus(List<NavLink> navLinks) {
|
| | | PageParameters params = getPageParameters();
|
| | |
|
| | | DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",
|
| | | DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",
|
| | | UserPage.class);
|
| | | // preserve time filter option on repository choices
|
| | | menu.menuItems.addAll(getRepositoryFilterItems(params));
|
| | |
| | |
|
| | | if (menu.menuItems.size() > 0) {
|
| | | // Reset Filter
|
| | | menu.menuItems.add(new DropDownMenuItem(getString("gb.reset"), null, null));
|
| | | menu.menuItems.add(new ParameterMenuItem(getString("gb.reset")));
|
| | | }
|
| | |
|
| | | pages.add(menu);
|
| | | navLinks.add(menu);
|
| | | }
|
| | |
|
| | | private void addPreferences(UserModel user) {
|
| | | // add preferences
|
| | | Form<Void> prefs = new Form<Void>("prefsForm");
|
| | |
|
| | | List<Language> languages = Arrays.asList(
|
| | | new Language("Deutsch","de"),
|
| | | new Language("English","en"),
|
| | | new Language("Español", "es"),
|
| | | new Language("Français", "fr"),
|
| | | new Language("Italiano", "it"),
|
| | | new Language("日本語", "ja"),
|
| | | new Language("한국말", "ko"),
|
| | | new Language("Nederlands", "nl"),
|
| | | new Language("Norsk", "no"),
|
| | | new Language("Język Polski", "pl"),
|
| | | new Language("Português", "pt_BR"),
|
| | | new Language("中文", "zh_CN"));
|
| | |
|
| | | Locale locale = user.getPreferences().getLocale();
|
| | | if (locale == null) {
|
| | | // user has not specified language preference
|
| | | // try server default preference
|
| | | String lc = app().settings().getString(Keys.web.forceDefaultLocale, null);
|
| | | if (StringUtils.isEmpty(lc)) {
|
| | | // server default language is not configured
|
| | | // try browser preference
|
| | | Locale sessionLocale = GitBlitWebSession.get().getLocale();
|
| | | if (sessionLocale != null) {
|
| | | locale = sessionLocale;
|
| | | }
|
| | | } else {
|
| | |
|
| | | }
|
| | | }
|
| | |
|
| | | Language preferredLanguage = null;
|
| | | if (locale != null) {
|
| | | String localeCode = locale.getLanguage();
|
| | | if (!StringUtils.isEmpty(locale.getCountry())) {
|
| | | localeCode += "_" + locale.getCountry();
|
| | | }
|
| | |
|
| | | for (Language language : languages) {
|
| | | if (language.code.equals(localeCode)) {
|
| | | // language_COUNTRY match
|
| | | preferredLanguage = language;
|
| | | } else if (preferredLanguage != null && language.code.startsWith(locale.getLanguage())) {
|
| | | // language match
|
| | | preferredLanguage = language;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | final IModel<String> displayName = Model.of(user.getDisplayName());
|
| | | final IModel<String> emailAddress = Model.of(user.emailAddress == null ? "" : user.emailAddress);
|
| | | final IModel<Language> language = Model.of(preferredLanguage);
|
| | | final IModel<Boolean> emailMeOnMyTicketChanges = Model.of(user.getPreferences().isEmailMeOnMyTicketChanges());
|
| | | final IModel<Transport> transport = Model.of(user.getPreferences().getTransport());
|
| | |
|
| | | prefs.add(new TextOption("displayName",
|
| | | getString("gb.displayName"),
|
| | | getString("gb.displayNameDescription"),
|
| | | displayName).setVisible(app().authentication().supportsDisplayNameChanges(user)));
|
| | |
|
| | | prefs.add(new TextOption("emailAddress",
|
| | | getString("gb.emailAddress"),
|
| | | getString("gb.emailAddressDescription"),
|
| | | emailAddress).setVisible(app().authentication().supportsEmailAddressChanges(user)));
|
| | |
|
| | | prefs.add(new ChoiceOption<Language>("language",
|
| | | getString("gb.languagePreference"),
|
| | | getString("gb.languagePreferenceDescription"),
|
| | | language,
|
| | | languages));
|
| | |
|
| | | prefs.add(new BooleanOption("emailMeOnMyTicketChanges",
|
| | | getString("gb.emailMeOnMyTicketChanges"),
|
| | | getString("gb.emailMeOnMyTicketChangesDescription"),
|
| | | emailMeOnMyTicketChanges).setVisible(app().notifier().isSendingMail()));
|
| | |
|
| | | List<Transport> availableTransports = new ArrayList<>();
|
| | | if (app().gitblit().isServingSSH()) {
|
| | | availableTransports.add(Transport.SSH);
|
| | | }
|
| | | if (app().gitblit().isServingHTTP()) {
|
| | | availableTransports.add(Transport.HTTPS);
|
| | | availableTransports.add(Transport.HTTP);
|
| | | }
|
| | | if (app().gitblit().isServingGIT()) {
|
| | | availableTransports.add(Transport.GIT);
|
| | | }
|
| | |
|
| | | prefs.add(new ChoiceOption<Transport>("transport",
|
| | | getString("gb.transportPreference"),
|
| | | getString("gb.transportPreferenceDescription"),
|
| | | transport,
|
| | | availableTransports));
|
| | |
|
| | | prefs.add(new AjaxButton("save") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
|
| | |
|
| | | UserModel user = GitBlitWebSession.get().getUser();
|
| | |
|
| | | user.displayName = displayName.getObject();
|
| | | user.emailAddress = emailAddress.getObject();
|
| | |
|
| | | Language lang = language.getObject();
|
| | | if (lang != null) {
|
| | | user.getPreferences().setLocale(lang.code);
|
| | | }
|
| | |
|
| | | user.getPreferences().setEmailMeOnMyTicketChanges(emailMeOnMyTicketChanges.getObject());
|
| | | user.getPreferences().setTransport(transport.getObject());
|
| | |
|
| | | try {
|
| | | app().gitblit().reviseUser(user.username, user);
|
| | |
|
| | | setRedirect(true);
|
| | | setResponsePage(UserPage.class, WicketUtils.newUsernameParameter(user.username));
|
| | | } catch (GitBlitException e) {
|
| | | // logger.error("Failed to update user " + user.username, e);
|
| | | // error(getString("gb.failedToUpdateUser"), false);
|
| | | }
|
| | | }
|
| | | });
|
| | |
|
| | | // add the preferences tab
|
| | | add(new Fragment("preferencesLink", "preferencesLinkFragment", this).setRenderBodyOnly(true));
|
| | | Fragment fragment = new Fragment("preferencesTab", "preferencesTabFragment", this);
|
| | | fragment.add(prefs);
|
| | | add(fragment.setRenderBodyOnly(true));
|
| | | }
|
| | |
|
| | | private void addSshKeys(final UserModel user) {
|
| | | Fragment keysTab = new Fragment("sshKeysTab", "sshKeysTabFragment", this);
|
| | | keysTab.add(new SshKeysPanel("sshKeysPanel", user));
|
| | |
|
| | | // add the SSH keys tab
|
| | | add(new Fragment("sshKeysLink", "sshKeysLinkFragment", this).setRenderBodyOnly(true));
|
| | | add(keysTab.setRenderBodyOnly(true));
|
| | | }
|
| | |
|
| | | private class Language implements Serializable {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | final String name;
|
| | | final String code;
|
| | |
|
| | | public Language(String name, String code) {
|
| | | this.name = name;
|
| | | this.code = code;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String toString() {
|
| | | return name + " (" + code +")";
|
| | | }
|
| | | }
|
| | | }
|
| | |
| | | <body>
|
| | | <wicket:extend>
|
| | | <div class="container">
|
| | | <div wicket:id="teamsPanel">[teams panel]</div>
|
| | |
|
| | | <div wicket:id="usersPanel">[users panel]</div>
|
| | | </div>
|
| | | </wicket:extend>
|
| | |
| | | package com.gitblit.wicket.pages;
|
| | |
|
| | | import com.gitblit.wicket.RequiresAdminRole;
|
| | | import com.gitblit.wicket.panels.TeamsPanel;
|
| | | import com.gitblit.wicket.panels.UsersPanel;
|
| | |
|
| | | @RequiresAdminRole
|
| | |
| | | public UsersPage() {
|
| | | super();
|
| | | setupPage("", "");
|
| | |
|
| | | add(new TeamsPanel("teamsPanel", showAdmin).setVisible(showAdmin));
|
| | |
|
| | | add(new UsersPanel("usersPanel", showAdmin).setVisible(showAdmin));
|
| | | }
|
New file |
| | |
| | | touch README.md |
| | | git init |
| | | git add README.md |
| | | git commit -m "first commit" |
| | | git remote add origin ${primaryUrl} |
| | | git push -u origin master |
New file |
| | |
| | | git remote add origin ${primaryUrl} |
| | | git push -u origin master |
| | |
| | | cd ${repo} |
| | | git checkout -b ${reviewBranch} origin/${integrationBranch} |
| | | ... |
| | | git push --set-upstream origin ${reviewBranch} |
| | | git push -u origin ${reviewBranch} |
| | | |
New file |
| | |
| | | <!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:panel>
|
| | |
|
| | | <h4><wicket:message key="gb.accessPolicy"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.accessPolicyDescription"></wicket:message></p>
|
| | | |
| | | <div wicket:id="policiesGroup">
|
| | | <div wicket:id="policies" style="padding-top:4px;">
|
| | | <div>
|
| | | <label style="font-weight:bold;margin-bottom:1px;"><input type="radio" wicket:id="radio" /> <img wicket:id="image"></img> <span wicket:id="name"></span></label>
|
| | | </div>
|
| | | <label class="checkbox" style="color:#777;" wicket:id="description"></label>
|
| | | </div>
|
| | | </div>
|
| | | |
| | | <div wicket:id="allowForks"></div>
|
| | | |
| | | <wicket:fragment wicket:id="allowForksFragment">
|
| | | <hr />
|
| | | |
| | | <div wicket:id="allowForks"></div>
|
| | | </wicket:fragment>
|
| | | </wicket:panel>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.panels;
|
| | |
|
| | | import java.io.Serializable;
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.Radio;
|
| | | import org.apache.wicket.markup.html.form.RadioGroup;
|
| | | import org.apache.wicket.markup.html.list.ListItem;
|
| | | import org.apache.wicket.markup.html.list.ListView;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.Constants.AuthorizationControl;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | |
|
| | | /**
|
| | | * A radio group panel of the 5 available authorization/access restriction combinations.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class AccessPolicyPanel extends BasePanel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | private final RepositoryModel repository;
|
| | |
|
| | | private final AjaxFormChoiceComponentUpdatingBehavior callback;
|
| | |
|
| | | private RadioGroup<AccessPolicy> policiesGroup;
|
| | |
|
| | | private IModel<Boolean> allowForks;
|
| | |
|
| | | public AccessPolicyPanel(String wicketId, RepositoryModel repository) {
|
| | | this(wicketId, repository, null);
|
| | | }
|
| | |
|
| | | public AccessPolicyPanel(String wicketId, RepositoryModel repository, AjaxFormChoiceComponentUpdatingBehavior callback) {
|
| | | super(wicketId);
|
| | | this.repository = repository;
|
| | | this.callback = callback;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void onInitialize() {
|
| | | super.onInitialize();
|
| | |
|
| | | AccessPolicy anonymousPolicy = new AccessPolicy(getString("gb.anonymousPolicy"),
|
| | | getString("gb.anonymousPolicyDescription"),
|
| | | "blank.png",
|
| | | AuthorizationControl.AUTHENTICATED,
|
| | | AccessRestrictionType.NONE);
|
| | |
|
| | | AccessPolicy authenticatedPushPolicy = new AccessPolicy(getString("gb.authenticatedPushPolicy"),
|
| | | getString("gb.authenticatedPushPolicyDescription"),
|
| | | "lock_go_16x16.png",
|
| | | AuthorizationControl.AUTHENTICATED,
|
| | | AccessRestrictionType.PUSH);
|
| | |
|
| | | AccessPolicy namedPushPolicy = new AccessPolicy(getString("gb.namedPushPolicy"),
|
| | | getString("gb.namedPushPolicyDescription"),
|
| | | "lock_go_16x16.png",
|
| | | AuthorizationControl.NAMED,
|
| | | AccessRestrictionType.PUSH);
|
| | |
|
| | | AccessPolicy clonePolicy = new AccessPolicy(getString("gb.clonePolicy"),
|
| | | getString("gb.clonePolicyDescription"),
|
| | | "lock_pull_16x16.png",
|
| | | AuthorizationControl.NAMED,
|
| | | AccessRestrictionType.CLONE);
|
| | |
|
| | | AccessPolicy viewPolicy = new AccessPolicy(getString("gb.viewPolicy"),
|
| | | getString("gb.viewPolicyDescription"),
|
| | | "shield_16x16.png",
|
| | | AuthorizationControl.NAMED,
|
| | | AccessRestrictionType.VIEW);
|
| | |
|
| | | List<AccessPolicy> policies = new ArrayList<AccessPolicy>();
|
| | | if (app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)) {
|
| | | policies.add(anonymousPolicy);
|
| | | }
|
| | | policies.add(authenticatedPushPolicy);
|
| | | policies.add(namedPushPolicy);
|
| | | policies.add(clonePolicy);
|
| | | policies.add(viewPolicy);
|
| | |
|
| | | AccessRestrictionType defaultRestriction = repository.accessRestriction;
|
| | | if (defaultRestriction == null) {
|
| | | defaultRestriction = AccessRestrictionType.fromName(app().settings().getString(Keys.git.defaultAccessRestriction,
|
| | | AccessRestrictionType.PUSH.name()));
|
| | | }
|
| | |
|
| | | AuthorizationControl defaultControl = repository.authorizationControl;
|
| | | if (defaultControl == null) {
|
| | | defaultControl = AuthorizationControl.fromName(app().settings().getString(Keys.git.defaultAuthorizationControl,
|
| | | AuthorizationControl.NAMED.name()));
|
| | | }
|
| | |
|
| | | AccessPolicy defaultPolicy = namedPushPolicy;
|
| | | for (AccessPolicy policy : policies) {
|
| | | if (policy.type == defaultRestriction && policy.control == defaultControl) {
|
| | | defaultPolicy = policy;
|
| | | }
|
| | | }
|
| | |
|
| | | policiesGroup = new RadioGroup<>("policiesGroup", new Model<AccessPolicy>(defaultPolicy));
|
| | | ListView<AccessPolicy> policiesList = new ListView<AccessPolicy>("policies", policies) {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | protected void populateItem(ListItem<AccessPolicy> item) {
|
| | | AccessPolicy p = item.getModelObject();
|
| | | item.add(new Radio<AccessPolicy>("radio", item.getModel()));
|
| | | item.add(WicketUtils.newImage("image", p.image));
|
| | | item.add(new Label("name", p.name));
|
| | | item.add(new Label("description", p.description));
|
| | | }
|
| | | };
|
| | | policiesGroup.add(policiesList);
|
| | | if (callback != null) {
|
| | | policiesGroup.add(callback);
|
| | | policiesGroup.setOutputMarkupId(true);
|
| | | }
|
| | | add(policiesGroup);
|
| | |
|
| | | allowForks = Model.of(app().settings().getBoolean(Keys.web.allowForking, true));
|
| | | if (allowForks.getObject()) {
|
| | | Fragment fragment = new Fragment("allowForks", "allowForksFragment", this);
|
| | | fragment.add(new BooleanOption("allowForks",
|
| | | getString("gb.allowForks"),
|
| | | getString("gb.allowForksDescription"),
|
| | | allowForks));
|
| | | add(fragment);
|
| | | } else {
|
| | | add(new Label("allowForks").setVisible(false));
|
| | | }
|
| | |
|
| | | setOutputMarkupId(true);
|
| | | }
|
| | |
|
| | | public void updateModel(RepositoryModel repository) {
|
| | | AccessPolicy policy = policiesGroup.getModelObject();
|
| | | repository.authorizationControl = policy.control;
|
| | | repository.accessRestriction = policy.type;
|
| | | repository.allowForks = allowForks.getObject();
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected boolean getStatelessHint() {
|
| | | return false;
|
| | | }
|
| | |
|
| | | public static class AccessPolicy implements Serializable {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | final String name;
|
| | | final String description;
|
| | | final String image;
|
| | | final AuthorizationControl control;
|
| | | final AccessRestrictionType type;
|
| | |
|
| | | AccessPolicy(String name, String description, String img, AuthorizationControl control, AccessRestrictionType type) {
|
| | | this.name = name;
|
| | | this.description = description;
|
| | | this.image = img;
|
| | | this.control = control;
|
| | | this.type = type;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String toString() {
|
| | | return name;
|
| | | }
|
| | | }
|
| | | }
|
| | |
| | | return GitBlitWebApp.get();
|
| | | }
|
| | |
|
| | | protected String getContextUrl() {
|
| | | return getRequest().getRelativePathPrefixToContextRoot();
|
| | | }
|
| | |
|
| | | protected TimeZone getTimeZone() {
|
| | | return app().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
|
| | | .getTimezone() : app().getTimezone();
|
New file |
| | |
| | | <!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:panel>
|
| | | <div style="padding-top:4px;">
|
| | | <div>
|
| | | <label style="font-weight:bold;margin-bottom:1px;" class="checkbox"><input type="checkbox" wicket:id="checkbox" /> <span wicket:id="name"></span></label>
|
| | | </div>
|
| | | <label class="checkbox" style="color:#777;"> <span wicket:id="description"></span>
|
| | | <p style="padding-top:5px;"><select class="span3" wicket:id="choice" /></p>
|
| | | </label> |
| | | </div>
|
| | | </wicket:panel>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.panels;
|
| | |
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.ajax.AjaxRequestTarget;
|
| | | import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.CheckBox;
|
| | | import org.apache.wicket.markup.html.form.DropDownChoice;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.parboiled.common.StringUtils;
|
| | |
|
| | | /**
|
| | | * A re-usable conditional choice option panel.
|
| | | *
|
| | | * [x] title
|
| | | * description
|
| | | * [choices]
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class BooleanChoiceOption<T> extends BasePanel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | final CheckBox checkbox;
|
| | | final DropDownChoice<T> choice;
|
| | |
|
| | | public BooleanChoiceOption(String wicketId, String title, String description, IModel<Boolean> checkboxModel, IModel<T> choiceModel, List<T> choices) {
|
| | | super(wicketId);
|
| | | add(new Label("name", title));
|
| | | add(new Label("description", description).setVisible(!StringUtils.isEmpty(description)));
|
| | |
|
| | | this.checkbox = new CheckBox("checkbox", checkboxModel);
|
| | | checkbox.setOutputMarkupId(true);
|
| | |
|
| | | this.choice = new DropDownChoice<T>("choice", choiceModel, choices);
|
| | | choice.setOutputMarkupId(true);
|
| | |
|
| | | setup();
|
| | | }
|
| | |
|
| | | private void setup() {
|
| | | add(checkbox);
|
| | | add(choice.setMarkupId("choice").setEnabled(choice.getChoices().size() > 0));
|
| | | choice.setEnabled(checkbox.getModelObject());
|
| | |
|
| | | checkbox.add(new AjaxFormComponentUpdatingBehavior("onchange") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | protected void onUpdate(AjaxRequestTarget target) {
|
| | | choice.setEnabled(checkbox.getModelObject());
|
| | | target.addComponent(choice);
|
| | | if (!choice.isEnabled()) {
|
| | | choice.setModelObject(null);
|
| | | }
|
| | | }
|
| | | });
|
| | | }
|
| | | }
|
New file |
| | |
| | | <!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:panel>
|
| | | <div style="padding-top:4px;">
|
| | | <div>
|
| | | <label style="font-weight:bold;margin-bottom:1px;" class="checkbox"><input type="checkbox" wicket:id="checkbox" /> <span wicket:id="name"></span></label>
|
| | | </div>
|
| | | <label class="checkbox" style="color:#777;" wicket:id="description"></label>
|
| | | </div>
|
| | | </wicket:panel>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.panels;
|
| | |
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.CheckBox;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.parboiled.common.StringUtils;
|
| | |
|
| | | /**
|
| | | * A re-usable checkbox option panel.
|
| | | *
|
| | | * [x] title
|
| | | * description
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class BooleanOption extends BasePanel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public BooleanOption(String wicketId, String title, String description, IModel<Boolean> model) {
|
| | | super(wicketId);
|
| | | add(new Label("name", title));
|
| | | add(new Label("description", description).setVisible(!StringUtils.isEmpty(description)));
|
| | | add(new CheckBox("checkbox", model));
|
| | | }
|
| | |
|
| | | public BooleanOption(String wicketId, String title, String description, CheckBox checkbox) {
|
| | | super(wicketId);
|
| | | add(new Label("name", title));
|
| | | add(new Label("description", description).setVisible(!StringUtils.isEmpty(description)));
|
| | | add(checkbox.setMarkupId("checkbox"));
|
| | | }
|
| | |
|
| | | public BooleanOption setIsHtmlDescription(boolean val) {
|
| | | ((Label) get("description")).setEscapeModelStrings(!val);
|
| | | return this;
|
| | | }
|
| | | }
|
| | |
| | | <!-- branch page links -->
|
| | | <wicket:fragment wicket:id="branchPageLinks">
|
| | | <span class="link">
|
| | | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | <a wicket:id="metrics"><wicket:message key="gb.metrics"></wicket:message></a> | <a wicket:id="syndication"><wicket:message key="gb.feed"></wicket:message></a>
|
| | | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | <a wicket:id="raw"><wicket:message key="gb.raw"></wicket:message></a> | <a wicket:id="metrics"><wicket:message key="gb.metrics"></wicket:message></a> | <a wicket:id="syndication"><wicket:message key="gb.feed"></wicket:message></a>
|
| | | </span>
|
| | | </wicket:fragment>
|
| | |
|
| | | <!-- branch page admin links -->
|
| | | <wicket:fragment wicket:id="branchPageAdminLinks">
|
| | | <span class="link">
|
| | | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | <a wicket:id="metrics"><wicket:message key="gb.metrics"></wicket:message></a> | <a wicket:id="syndication"><wicket:message key="gb.feed"></wicket:message></a> | <a wicket:id="deleteBranch"><wicket:message key="gb.delete"></wicket:message></a>
|
| | | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | <a wicket:id="raw"><wicket:message key="gb.raw"></wicket:message></a> | <a wicket:id="metrics"><wicket:message key="gb.metrics"></wicket:message></a> | <a wicket:id="syndication"><wicket:message key="gb.feed"></wicket:message></a> | <a wicket:id="deleteBranch"><wicket:message key="gb.delete"></wicket:message></a>
|
| | | </span>
|
| | | </wicket:fragment>
|
| | |
|
| | | <!-- branch panel links -->
|
| | | <wicket:fragment wicket:id="branchPanelLinks">
|
| | | <span class="link">
|
| | | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a>
|
| | | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | <a wicket:id="raw"><wicket:message key="gb.raw"></wicket:message></a>
|
| | | </span>
|
| | | </wicket:fragment>
|
| | |
|
| | |
| | | import com.gitblit.models.RefModel;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.servlet.RawServlet;
|
| | | import com.gitblit.servlet.SyndicationServlet;
|
| | | import com.gitblit.utils.CommitCache;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | |
| | | .newObjectParameter(model.name, entry.getName())));
|
| | | fragment.add(new BookmarkablePageLink<Void>("tree", TreePage.class, WicketUtils
|
| | | .newObjectParameter(model.name, entry.getName())));
|
| | | String rawUrl = RawServlet.asLink(getContextUrl(), model.name, Repository.shortenRefName(entry.getName()), null);
|
| | | fragment.add(new ExternalLink("raw", rawUrl));
|
| | | fragment.add(new BookmarkablePageLink<Void>("metrics", MetricsPage.class,
|
| | | WicketUtils.newObjectParameter(model.name, entry.getName())));
|
| | | fragment.add(new ExternalLink("syndication", SyndicationServlet.asLink(
|
| | |
| | | .newObjectParameter(model.name, entry.getName())));
|
| | | fragment.add(new BookmarkablePageLink<Void>("tree", TreePage.class, WicketUtils
|
| | | .newObjectParameter(model.name, entry.getName())));
|
| | | String rawUrl = RawServlet.asLink(getContextUrl(), model.name, Repository.shortenRefName(entry.getName()), null);
|
| | | fragment.add(new ExternalLink("raw", rawUrl));
|
| | | item.add(fragment);
|
| | | }
|
| | | WicketUtils.setAlternatingBackground(item, counter);
|
New file |
| | |
| | | <!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:panel>
|
| | | <div style="padding-top:4px;">
|
| | | <div style="margin-bottom:1px;">
|
| | | <b><span wicket:id="name"></span></b>
|
| | | </div>
|
| | | <label class="checkbox" style="color:#777;"> <span wicket:id="description"></span>
|
| | | <p style="padding-top:5px;"><select class="span3" wicket:id="choice" /></p>
|
| | | </label> |
| | | </div>
|
| | | </wicket:panel>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.panels;
|
| | |
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.DropDownChoice;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.parboiled.common.StringUtils;
|
| | |
|
| | | /**
|
| | | * A re-usable choice option panel.
|
| | | *
|
| | | * title
|
| | | * description
|
| | | * [choices]
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class ChoiceOption<T> extends BasePanel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public ChoiceOption(String wicketId, String title, String description, IModel<T> model, List<T> choices) {
|
| | | super(wicketId);
|
| | | add(new Label("name", title));
|
| | | add(new Label("description", description).setVisible(!StringUtils.isEmpty(description)));
|
| | | add(new DropDownChoice<>("choice", model, choices).setEnabled(choices.size() > 0));
|
| | | }
|
| | |
|
| | | public ChoiceOption(String wicketId, String title, String description, DropDownChoice<?> choice) {
|
| | | super(wicketId);
|
| | | add(new Label("name", title));
|
| | | add(new Label("description", description).setVisible(!StringUtils.isEmpty(description)));
|
| | | add(choice.setMarkupId("choice").setEnabled(choice.getChoices().size() > 0));
|
| | | }
|
| | | }
|
| | |
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
| | |
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
|
| | | import com.gitblit.models.Menu.ExternalLinkMenuItem;
|
| | | import com.gitblit.models.Menu.MenuDivider;
|
| | | import com.gitblit.models.Menu.MenuItem;
|
| | | import com.gitblit.models.Menu.PageLinkMenuItem;
|
| | | import com.gitblit.models.Menu.ParameterMenuItem;
|
| | | import com.gitblit.models.NavLink.DropDownMenuNavLink;
|
| | | import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | |
|
| | | public class DropDownMenu extends Panel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public DropDownMenu(String id, String label, final DropDownMenuRegistration menu) {
|
| | | public DropDownMenu(String id, String label, final DropDownPageMenuNavLink menu) {
|
| | | super(id);
|
| | |
|
| | | add(new Label("label", label).setRenderBodyOnly(true));
|
| | | ListDataProvider<DropDownMenuItem> items = new ListDataProvider<DropDownMenuItem>(
|
| | | menu.menuItems);
|
| | | DataView<DropDownMenuItem> view = new DataView<DropDownMenuItem>("menuItems", items) {
|
| | | ListDataProvider<MenuItem> items = new ListDataProvider<MenuItem>(menu.menuItems);
|
| | | DataView<MenuItem> view = new DataView<MenuItem>("menuItems", items) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void populateItem(final Item<DropDownMenuItem> item) {
|
| | | DropDownMenuItem entry = item.getModelObject();
|
| | | if (entry.isDivider()) {
|
| | | public void populateItem(final Item<MenuItem> item) {
|
| | | MenuItem entry = item.getModelObject();
|
| | | if (entry instanceof PageLinkMenuItem) {
|
| | | // link to another Wicket page
|
| | | PageLinkMenuItem pageLink = (PageLinkMenuItem) entry;
|
| | | item.add(new LinkPanel("menuItem", null, null, pageLink.toString(), pageLink.getPageClass(),
|
| | | pageLink.getPageParameters(), false).setRenderBodyOnly(true));
|
| | | } else if (entry instanceof ExternalLinkMenuItem) {
|
| | | // link to a specified href
|
| | | ExternalLinkMenuItem extLink = (ExternalLinkMenuItem) entry;
|
| | | item.add(new LinkPanel("menuItem", null, extLink.toString(), extLink.getHref(),
|
| | | extLink.openInNewWindow()).setRenderBodyOnly(true));
|
| | | } else if (entry instanceof MenuDivider) {
|
| | | // divider
|
| | | item.add(new Label("menuItem").setRenderBodyOnly(true));
|
| | | WicketUtils.setCssClass(item, "divider");
|
| | | } else {
|
| | | ParameterMenuItem parameter = (ParameterMenuItem) entry;
|
| | | // parameter link for the current page
|
| | | String icon = null;
|
| | | if (entry.isSelected()) {
|
| | | if (parameter.isSelected()) {
|
| | | icon = "icon-ok";
|
| | | } else {
|
| | | icon = "icon-ok-white";
|
| | | }
|
| | | item.add(new LinkPanel("menuItem", icon, null, entry.toString(), menu.pageClass,
|
| | | entry.getPageParameters(), false).setRenderBodyOnly(true));
|
| | | parameter.getPageParameters(), false).setRenderBodyOnly(true));
|
| | | }
|
| | | }
|
| | | };
|
| | | add(view);
|
| | | setRenderBodyOnly(true);
|
| | | }
|
| | |
|
| | | public DropDownMenu(String id, String label, final DropDownMenuNavLink menu) {
|
| | | super(id);
|
| | |
|
| | | add(new Label("label", label).setRenderBodyOnly(true));
|
| | | ListDataProvider<MenuItem> items = new ListDataProvider<MenuItem>(menu.menuItems);
|
| | | DataView<MenuItem> view = new DataView<MenuItem>("menuItems", items) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void populateItem(final Item<MenuItem> item) {
|
| | | MenuItem entry = item.getModelObject();
|
| | | if (entry instanceof PageLinkMenuItem) {
|
| | | // link to another Wicket page
|
| | | PageLinkMenuItem pageLink = (PageLinkMenuItem) entry;
|
| | | item.add(new LinkPanel("menuItem", null, null, pageLink.toString(), pageLink.getPageClass(),
|
| | | pageLink.getPageParameters(), false).setRenderBodyOnly(true));
|
| | | } else if (entry instanceof ExternalLinkMenuItem) {
|
| | | // link to a specified href
|
| | | ExternalLinkMenuItem extLink = (ExternalLinkMenuItem) entry;
|
| | | item.add(new LinkPanel("menuItem", null, extLink.toString(), extLink.getHref(),
|
| | | extLink.openInNewWindow()).setRenderBodyOnly(true));
|
| | | } else if (entry instanceof MenuDivider) {
|
| | | // divider
|
| | | item.add(new Label("menuItem").setRenderBodyOnly(true));
|
| | | WicketUtils.setCssClass(item, "divider");
|
| | | } else {
|
| | | throw new IllegalArgumentException(String.format("Unexpected menuitem type %s",
|
| | | entry.getClass().getSimpleName()));
|
| | | }
|
| | | }
|
| | | };
|
| | |
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.freemarker.FreemarkerPanel;
|
| | | import com.gitblit.wicket.ng.NgController;
|
| | | import com.gitblit.wicket.pages.EditRepositoryPage;
|
| | |
|
| | | /**
|
| | | * A client-side filterable rich repository list which uses Freemarker, Wicket,
|
| | |
| | | }
|
| | |
|
| | | if (allowCreate) {
|
| | | panel.add(new LinkPanel(ngList + "Button", "btn btn-mini", getString("gb.newRepository"), EditRepositoryPage.class));
|
| | | panel.add(new LinkPanel(ngList + "Button", "btn btn-mini", getString("gb.newRepository"), app().getNewRepositoryPage()));
|
| | | } else {
|
| | | panel.add(new Label(ngList + "Button").setVisible(false));
|
| | | }
|
| | |
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
| | |
|
| | | import com.gitblit.wicket.PageRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.OtherPageLink;
|
| | | import com.gitblit.models.NavLink;
|
| | | import com.gitblit.models.NavLink.DropDownMenuNavLink;
|
| | | import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
|
| | | import com.gitblit.models.NavLink.ExternalNavLink;
|
| | | import com.gitblit.models.NavLink.PageNavLink;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.pages.BasePage;
|
| | |
|
| | |
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public NavigationPanel(String id, final Class<? extends BasePage> pageClass,
|
| | | List<PageRegistration> registeredPages) {
|
| | | List<NavLink> navLinks) {
|
| | | super(id);
|
| | |
|
| | | ListDataProvider<PageRegistration> refsDp = new ListDataProvider<PageRegistration>(
|
| | | registeredPages);
|
| | | DataView<PageRegistration> refsView = new DataView<PageRegistration>("navLink", refsDp) {
|
| | | ListDataProvider<NavLink> refsDp = new ListDataProvider<NavLink>(navLinks);
|
| | | DataView<NavLink> linksView = new DataView<NavLink>("navLink", refsDp) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void populateItem(final Item<PageRegistration> item) {
|
| | | PageRegistration entry = item.getModelObject();
|
| | | if (entry.hiddenPhone) {
|
| | | public void populateItem(final Item<NavLink> item) {
|
| | | NavLink navLink = item.getModelObject();
|
| | | String linkText = navLink.translationKey;
|
| | | try {
|
| | | // try to lookup translation key
|
| | | linkText = getString(navLink.translationKey);
|
| | | } catch (Exception e) {
|
| | | }
|
| | |
|
| | | if (navLink.hiddenPhone) {
|
| | | WicketUtils.setCssClass(item, "hidden-phone");
|
| | | }
|
| | | if (entry instanceof OtherPageLink) {
|
| | | if (navLink instanceof ExternalNavLink) {
|
| | | // other link
|
| | | OtherPageLink link = (OtherPageLink) entry;
|
| | | Component c = new LinkPanel("link", null, getString(entry.translationKey), link.url);
|
| | | ExternalNavLink link = (ExternalNavLink) navLink;
|
| | | Component c = new LinkPanel("link", null, linkText, link.url);
|
| | | c.setRenderBodyOnly(true);
|
| | | item.add(c);
|
| | | } else if (entry instanceof DropDownMenuRegistration) {
|
| | | } else if (navLink instanceof DropDownPageMenuNavLink) {
|
| | | // drop down menu
|
| | | DropDownMenuRegistration reg = (DropDownMenuRegistration) entry;
|
| | | Component c = new DropDownMenu("link", getString(entry.translationKey), reg);
|
| | | DropDownPageMenuNavLink reg = (DropDownPageMenuNavLink) navLink;
|
| | | Component c = new DropDownMenu("link", linkText, reg);
|
| | | c.setRenderBodyOnly(true);
|
| | | item.add(c);
|
| | | WicketUtils.setCssClass(item, "dropdown");
|
| | | } else {
|
| | | // standard page link
|
| | | Component c = new LinkPanel("link", null, getString(entry.translationKey),
|
| | | entry.pageClass, entry.params);
|
| | | } else if (navLink instanceof DropDownMenuNavLink) {
|
| | | // drop down menu
|
| | | DropDownMenuNavLink reg = (DropDownMenuNavLink) navLink;
|
| | | Component c = new DropDownMenu("link", linkText, reg);
|
| | | c.setRenderBodyOnly(true);
|
| | | if (entry.pageClass.equals(pageClass)) {
|
| | | item.add(c);
|
| | | WicketUtils.setCssClass(item, "dropdown");
|
| | | } else if (navLink instanceof PageNavLink) {
|
| | | PageNavLink reg = (PageNavLink) navLink;
|
| | | // standard page link
|
| | | Component c = new LinkPanel("link", null, linkText,
|
| | | reg.pageClass, reg.params);
|
| | | c.setRenderBodyOnly(true);
|
| | | if (reg.pageClass.equals(pageClass)) {
|
| | | WicketUtils.setCssClass(item, "active");
|
| | | }
|
| | | item.add(c);
|
| | | }
|
| | | }
|
| | | };
|
| | | add(refsView);
|
| | | add(linksView);
|
| | | }
|
| | | } |
| | |
| | | lang="en">
|
| | |
|
| | | <wicket:panel>
|
| | | <wicket:fragment wicket:id="repositoryAdminLinks">
|
| | | <span class="link">
|
| | | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a>
|
| | | | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a>
|
| | | | <a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a>
|
| | | | <a wicket:id="deleteRepository"><wicket:message key="gb.delete">[delete]</wicket:message></a>
|
| | | </span>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="repositoryOwnerLinks">
|
| | | <span class="link">
|
| | | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a>
|
| | |
| | | */
|
| | | package com.gitblit.wicket.panels;
|
| | |
|
| | | import java.text.MessageFormat;
|
| | | import java.util.Map;
|
| | |
|
| | | import org.apache.wicket.Component;
|
| | |
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | | import org.apache.wicket.markup.html.link.Link;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | |
| | | user = UserModel.ANONYMOUS;
|
| | | }
|
| | | Fragment repositoryLinks;
|
| | | boolean showOwner = entry.isOwner(user.username);
|
| | | // owner of personal repository gets admin powers
|
| | | boolean showAdmin = isAdmin || entry.isUsersPersonalRepository(user.username);
|
| | |
|
| | | if (showAdmin || showOwner) {
|
| | | repositoryLinks = new Fragment("repositoryLinks", showAdmin ? "repositoryAdminLinks"
|
| | | : "repositoryOwnerLinks", this);
|
| | | if (user.canAdmin(entry)) {
|
| | | repositoryLinks = new Fragment("repositoryLinks", "repositoryOwnerLinks", this);
|
| | | repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", EditRepositoryPage.class,
|
| | | WicketUtils.newRepositoryParameter(entry.name)));
|
| | | if (showAdmin) {
|
| | | Link<Void> deleteLink = new Link<Void>("deleteRepository") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void onClick() {
|
| | | if (app().repositories().deleteRepositoryModel(entry)) {
|
| | | // redirect to the owning page
|
| | | if (entry.isPersonalRepository()) {
|
| | | setResponsePage(getPage().getClass(), WicketUtils.newUsernameParameter(entry.projectPath.substring(1)));
|
| | | } else {
|
| | | setResponsePage(getPage().getClass(), WicketUtils.newProjectParameter(entry.projectPath));
|
| | | }
|
| | | } else {
|
| | | error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), entry));
|
| | | }
|
| | | }
|
| | | };
|
| | | deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format(
|
| | | localizer.getString("gb.deleteRepository", parent), entry)));
|
| | | repositoryLinks.add(deleteLink);
|
| | | }
|
| | | } else {
|
| | | repositoryLinks = new Fragment("repositoryLinks", "repositoryUserLinks", this);
|
| | | }
|
| | |
| | | </form>
|
| | |
|
| | | <div style="clear:both;" wicket:id="permissionRow">
|
| | | <div style="padding-top:10px;border-left:1px solid #ccc;border-right:1px solid #ccc;" class="row-fluid">
|
| | | <div style="padding-top:10px;" class="row-fluid">
|
| | | <div style="padding-top:5px;padding-left:5px" class="span6"><span wicket:id="registrant"></span></div><div style="padding-top:5px;padding-right:5px;text-align:right;" class="span3"><span class="label" wicket:id="pType">[permission type]</span></div> <select class="input-medium" wicket:id="permission"></select>
|
| | | </div>
|
| | | </div>
|
| | |
| | | </div>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="repositoryAdminLinks">
|
| | | <span class="link"><a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a> | <a wicket:id="deleteRepository"><wicket:message key="gb.delete">[delete]</wicket:message></a></span>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="repositoryOwnerLinks">
|
| | | <span class="link"><a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a></span>
|
| | | </wicket:fragment>
|
| | |
|
| | | <wicket:fragment wicket:id="flatRepositoryHeader">
|
| | | <tr>
|
| | | <th class="left" wicket:id="orderByRepository">
|
| | |
| | | <th class="hidden-tablet hidden-phone" wicket:id="orderByOwner"><wicket:message key="gb.owner">Owner</wicket:message></th>
|
| | | <th class="hidden-phone"></th>
|
| | | <th wicket:id="orderByDate"><wicket:message key="gb.lastChange">Last Change</wicket:message></th>
|
| | | <th class="hidden-phone"></th>
|
| | | <th class="right"></th>
|
| | | <th class="right hidden-phone"></th>
|
| | | </tr>
|
| | | </wicket:fragment>
|
| | |
|
| | |
| | | <th class="hidden-tablet hidden-phone"><span><wicket:message key="gb.owner">Owner</wicket:message></span></th>
|
| | | <th class="hidden-phone"></th>
|
| | | <th><wicket:message key="gb.lastChange">Last Change</wicket:message></th>
|
| | | <th class="hidden-phone"></th>
|
| | | <th class="right"></th>
|
| | | <th class="right hidden-phone"></th>
|
| | | </tr>
|
| | | </wicket:fragment>
|
| | |
|
| | |
| | | <td class="hidden-tablet hidden-phone author"><span wicket:id="repositoryOwner">[repository owner]</span></td>
|
| | | <td class="hidden-phone" style="text-align: right;padding-right:10px;"><img class="inlineIcon" wicket:id="sparkleshareIcon" /><img class="inlineIcon" wicket:id="mirrorIcon" /><img class="inlineIcon" wicket:id="forkIcon" /><img class="inlineIcon" wicket:id="frozenIcon" /><img class="inlineIcon" wicket:id="federatedIcon" /><img class="inlineIcon" wicket:id="accessRestrictionIcon" /></td>
|
| | | <td><span wicket:id="repositoryLastChange">[last change]</span></td>
|
| | | <td class="hidden-phone" style="text-align: right;padding-right:15px;"><span style="font-size:0.8em;" wicket:id="repositorySize">[repository size]</span></td>
|
| | | <td class="rightAlign">
|
| | | <span class="hidden-phone">
|
| | | <span wicket:id="repositoryLinks"></span>
|
| | | <a style="text-decoration: none;" wicket:id="syndication" wicket:message="title:gb.feed">
|
| | | <img style="border:0px;vertical-align:middle;" src="feed_16x16.png"></img>
|
| | | </a>
|
| | | </span>
|
| | | </td> |
| | | <td class="rightAlign hidden-phone" style="text-align: right;padding-right:15px;"><span style="font-size:0.8em;" wicket:id="repositorySize">[repository size]</span></td>
|
| | | </wicket:fragment>
|
| | |
|
| | | </wicket:panel>
|
| | |
| | | */
|
| | | package com.gitblit.wicket.panels;
|
| | |
|
| | | import java.text.MessageFormat;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Collections;
|
| | | import java.util.Comparator;
|
| | |
| | | import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | | import org.apache.wicket.markup.html.link.Link;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.apache.wicket.markup.repeater.Item;
|
| | |
| | | import com.gitblit.models.ProjectModel;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.servlet.SyndicationServlet;
|
| | | import com.gitblit.utils.ArrayUtils;
|
| | | import com.gitblit.utils.ModelUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.pages.BasePage;
|
| | | import com.gitblit.wicket.pages.EditRepositoryPage;
|
| | | import com.gitblit.wicket.pages.EmptyRepositoryPage;
|
| | | import com.gitblit.wicket.pages.ProjectPage;
|
| | | import com.gitblit.wicket.pages.RepositoriesPage;
|
| | | import com.gitblit.wicket.pages.SummaryPage;
|
| | |
| | | setResponsePage(RepositoriesPage.class);
|
| | | }
|
| | | }.setVisible(app().settings().getBoolean(Keys.git.cacheRepositoryList, true)));
|
| | | managementLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
|
| | | managementLinks.add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));
|
| | | add(managementLinks);
|
| | | } else if (showManagement && user != null && user.canCreate()) {
|
| | | // user can create personal repositories
|
| | | managementLinks = new Fragment("managementPanel", "personalLinks", this);
|
| | | managementLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
|
| | | managementLinks.add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));
|
| | | add(managementLinks);
|
| | | } else {
|
| | | // user has no management permissions
|
| | |
| | | Collections.sort(subModels);
|
| | | groupedModels.addAll(subModels);
|
| | | }
|
| | | dp = new RepositoriesProvider(groupedModels);
|
| | | dp = new ListDataProvider<RepositoryModel>(groupedModels);
|
| | | } else {
|
| | | dp = new SortableRepositoriesProvider(models);
|
| | | }
|
| | |
|
| | | final String baseUrl = WicketUtils.getGitblitURL(getRequest());
|
| | | final boolean showSwatch = app().settings().getBoolean(Keys.web.repositoryListSwatches, true);
|
| | |
|
| | | DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) {
|
| | |
| | | swatch.setVisible(showSwatch);
|
| | |
|
| | | if (linksActive) {
|
| | | Class<? extends BasePage> linkPage;
|
| | | if (entry.hasCommits) {
|
| | | // repository has content
|
| | | linkPage = SummaryPage.class;
|
| | | } else {
|
| | | // new/empty repository OR proposed repository
|
| | | linkPage = EmptyRepositoryPage.class;
|
| | | }
|
| | |
|
| | | Class<? extends BasePage> linkPage = SummaryPage.class;
|
| | | PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);
|
| | | row.add(new LinkPanel("repositoryName", "list", repoName, linkPage, pp));
|
| | | row.add(new LinkPanel("repositoryDescription", "list", entry.description,
|
| | |
| | | WicketUtils.setHtmlTooltip(lastChangeLabel, getString("gb.author") + ": " + entry.lastChangeAuthor);
|
| | | }
|
| | |
|
| | | boolean showOwner = user != null && entry.isOwner(user.username);
|
| | | boolean myPersonalRepository = showOwner && entry.isUsersPersonalRepository(user.username);
|
| | | if (showAdmin || myPersonalRepository) {
|
| | | Fragment repositoryLinks = new Fragment("repositoryLinks",
|
| | | "repositoryAdminLinks", this);
|
| | | repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository",
|
| | | EditRepositoryPage.class, WicketUtils
|
| | | .newRepositoryParameter(entry.name)));
|
| | | Link<Void> deleteLink = new Link<Void>("deleteRepository") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void onClick() {
|
| | | if (app().repositories().deleteRepositoryModel(entry)) {
|
| | | if (dp instanceof SortableRepositoriesProvider) {
|
| | | info(MessageFormat.format(getString("gb.repositoryDeleted"), entry));
|
| | | ((SortableRepositoriesProvider) dp).remove(entry);
|
| | | } else {
|
| | | setResponsePage(getPage().getClass(), getPage().getPageParameters());
|
| | | }
|
| | | } else {
|
| | | error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), entry));
|
| | | }
|
| | | }
|
| | | };
|
| | | deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format(
|
| | | getString("gb.deleteRepository"), entry)));
|
| | | repositoryLinks.add(deleteLink);
|
| | | row.add(repositoryLinks);
|
| | | } else if (showOwner) {
|
| | | Fragment repositoryLinks = new Fragment("repositoryLinks",
|
| | | "repositoryOwnerLinks", this);
|
| | | repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository",
|
| | | EditRepositoryPage.class, WicketUtils
|
| | | .newRepositoryParameter(entry.name)));
|
| | | row.add(repositoryLinks);
|
| | | } else {
|
| | | row.add(new Label("repositoryLinks"));
|
| | | }
|
| | | row.add(new ExternalLink("syndication", SyndicationServlet.asLink(baseUrl,
|
| | | entry.name, null, 0)).setVisible(linksActive));
|
| | | WicketUtils.setAlternatingBackground(item, counter);
|
| | | counter++;
|
| | | }
|
| | |
| | | };
|
| | | }
|
| | |
|
| | | private static class RepositoriesProvider extends ListDataProvider<RepositoryModel> {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public RepositoriesProvider(List<RepositoryModel> list) {
|
| | | super(list);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public List<RepositoryModel> getData() {
|
| | | return super.getData();
|
| | | }
|
| | |
|
| | | public void remove(RepositoryModel model) {
|
| | | int index = getData().indexOf(model);
|
| | | RepositoryModel groupModel = null;
|
| | | if (index == (getData().size() - 1)) {
|
| | | // last element
|
| | | if (index > 0) {
|
| | | // previous element is group header, then this is last
|
| | | // repository in group. remove group too.
|
| | | if (getData().get(index - 1) instanceof GroupRepositoryModel) {
|
| | | groupModel = getData().get(index - 1);
|
| | | }
|
| | | }
|
| | | } else if (index < (getData().size() - 1)) {
|
| | | // not last element. check next element for group match.
|
| | | if (getData().get(index - 1) instanceof GroupRepositoryModel
|
| | | && getData().get(index + 1) instanceof GroupRepositoryModel) {
|
| | | // repository is sandwiched by group headers so this
|
| | | // repository is the only element in the group. remove
|
| | | // group.
|
| | | groupModel = getData().get(index - 1);
|
| | | }
|
| | | }
|
| | |
|
| | | if (groupModel == null) {
|
| | | // Find the group and decrement the count
|
| | | for (int i = index; i >= 0; i--) {
|
| | | if (getData().get(i) instanceof GroupRepositoryModel) {
|
| | | ((GroupRepositoryModel) getData().get(i)).count--;
|
| | | break;
|
| | | }
|
| | | }
|
| | | } else {
|
| | | // Remove the group header
|
| | | getData().remove(groupModel);
|
| | | }
|
| | |
|
| | | getData().remove(model);
|
| | | }
|
| | | }
|
| | |
|
| | | private static class SortableRepositoriesProvider extends SortableDataProvider<RepositoryModel> {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
| | | protected SortableRepositoriesProvider(List<RepositoryModel> list) {
|
| | | this.list = list;
|
| | | setSort(SortBy.date.name(), false);
|
| | | }
|
| | |
|
| | | public void remove(RepositoryModel model) {
|
| | | list.remove(model);
|
| | | }
|
| | |
|
| | | @Override
|
New file |
| | |
| | | <!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:panel>
|
| | |
|
| | | <table class="plain">
|
| | | <tbody class="settings">
|
| | | <tr>
|
| | | <th><wicket:message key="gb.project"></wicket:message></th>
|
| | | <th><wicket:message key="gb.name"></wicket:message></th>
|
| | | </tr>
|
| | | <tr>
|
| | | <td><select class="span2" wicket:id="projectPath" /></td>
|
| | | <td class="edit"><input class="span4" type="text" wicket:id="name" id="name" /> <span class="help-inline"><wicket:message key="gb.nameDescription"></wicket:message></span></td>
|
| | | </tr>
|
| | | </tbody>
|
| | | </table>
|
| | | |
| | | <div>
|
| | | <b><wicket:message key="gb.description"></wicket:message></b><br/>
|
| | | <input class="span5" type="text" wicket:id="description" />
|
| | | </div>
|
| | | |
| | | </wicket:panel>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.panels;
|
| | |
|
| | | import java.text.MessageFormat;
|
| | | import java.util.ArrayList;
|
| | | import java.util.Set;
|
| | | import java.util.TreeSet;
|
| | |
|
| | | import org.apache.wicket.markup.html.form.DropDownChoice;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | |
|
| | | import com.gitblit.models.ProjectModel;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | |
|
| | | /**
|
| | | * A panel for naming a repository, specifying it's project, and entering a description.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class RepositoryNamePanel extends BasePanel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | private String fullName;
|
| | |
|
| | | private final IModel<String> projectPath;
|
| | |
|
| | | private DropDownChoice<String> pathChoice;
|
| | |
|
| | | private final IModel<String> repoName;
|
| | |
|
| | | private TextField<String> nameField;
|
| | |
|
| | | public RepositoryNamePanel(String wicketId, RepositoryModel repository) {
|
| | | super(wicketId);
|
| | |
|
| | | GitBlitWebSession session = GitBlitWebSession.get();
|
| | | UserModel user = session.getUser();
|
| | |
|
| | | // build project set for repository destination
|
| | | String defaultPath = null;
|
| | | String defaultName = null;
|
| | | Set<String> pathNames = new TreeSet<String>();
|
| | |
|
| | | // add the registered/known projects
|
| | | for (ProjectModel project : app().projects().getProjectModels(user, false)) {
|
| | | // TODO issue-351: user.canAdmin(project)
|
| | | if (user.canAdmin()) {
|
| | | if (project.isRoot) {
|
| | | pathNames.add("/");
|
| | | } else {
|
| | | pathNames.add(project.name + "/");
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | // add the user's personal project namespace
|
| | | if (user.canAdmin() || user.canCreate()) {
|
| | | pathNames.add(user.getPersonalPath() + "/");
|
| | | }
|
| | |
|
| | | if (!StringUtils.isEmpty(repository.name)) {
|
| | | // editing a repository name
|
| | | // set the defaultProject to the current repository project
|
| | | if (StringUtils.isEmpty(repository.projectPath)) {
|
| | | defaultPath = "/";
|
| | | defaultName = repository.name;
|
| | | } else {
|
| | | defaultPath = repository.projectPath + "/";
|
| | | defaultName = repository.name.substring(defaultPath.length());
|
| | | }
|
| | | pathNames.add(defaultPath);
|
| | | }
|
| | |
|
| | | // if default project is not already set, set preference based on the user permissions
|
| | | if (defaultPath == null) {
|
| | | if (user.canAdmin()) {
|
| | | defaultPath = "/";
|
| | | } else if (user.canCreate()) {
|
| | | defaultPath = user.getPersonalPath() + "/";
|
| | | }
|
| | | }
|
| | |
|
| | | projectPath = Model.of(defaultPath);
|
| | | pathChoice = new DropDownChoice<String>("projectPath", projectPath, new ArrayList<String>(pathNames));
|
| | | repoName = Model.of(defaultName);
|
| | | nameField = new TextField<String>("name", repoName);
|
| | |
|
| | | // only enable project selection if we actually have multiple choices
|
| | | add(pathChoice.setEnabled(pathNames.size() > 1));
|
| | | add(nameField);
|
| | | add(new TextField<String>("description"));
|
| | | }
|
| | |
|
| | | public void setEditable(boolean editable) {
|
| | | // only enable project selection if we actually have multiple choices
|
| | | pathChoice.setEnabled(pathChoice.getChoices().size() > 1 && editable);
|
| | | nameField.setEnabled(editable);
|
| | | }
|
| | |
|
| | | public boolean updateModel(RepositoryModel repositoryModel) {
|
| | | // confirm a project path was selected
|
| | | if (StringUtils.isEmpty(projectPath.getObject())) {
|
| | | error(getString("gb.pleaseSelectProject"));
|
| | | return false;
|
| | | }
|
| | |
|
| | | // confirm a repository name was entered
|
| | | if (StringUtils.isEmpty(repoName.getObject())) {
|
| | | error(getString("gb.pleaseSetRepositoryName"));
|
| | | return false;
|
| | | }
|
| | |
|
| | | String project = projectPath.getObject();
|
| | | String name = repoName.getObject();
|
| | |
|
| | | fullName = (project + name).trim();
|
| | | fullName = fullName.replace('\\', '/');
|
| | | fullName = fullName.replace("//", "/");
|
| | | if (fullName.charAt(0) == '/') {
|
| | | fullName = fullName.substring(1);
|
| | | }
|
| | | if (fullName.endsWith("/")) {
|
| | | fullName = fullName.substring(0, fullName.length() - 1);
|
| | | }
|
| | |
|
| | | if (fullName.contains("../")) {
|
| | | error(getString("gb.illegalRelativeSlash"));
|
| | | return false;
|
| | | }
|
| | | if (fullName.contains("/../")) {
|
| | | error(getString("gb.illegalRelativeSlash"));
|
| | | return false;
|
| | | }
|
| | |
|
| | | // confirm valid characters in repository name
|
| | | Character c = StringUtils.findInvalidCharacter(fullName);
|
| | | if (c != null) {
|
| | | error(MessageFormat.format(getString("gb.illegalCharacterRepositoryName"), c));
|
| | | return false;
|
| | | }
|
| | |
|
| | | repositoryModel.name = fullName;
|
| | |
|
| | | return true;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected boolean getStatelessHint() {
|
| | | return false;
|
| | | }
|
| | | } |
New file |
| | |
| | | <!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:panel>
|
| | | <h4><wicket:message key="gb.sshKeys"></wicket:message></h4>
|
| | | <p><wicket:message key="gb.sshKeysDescription"></wicket:message></p>
|
| | | <hr />
|
| | | |
| | | <div wicket:id="keys">
|
| | | <div style="display:inline-block;font-size:2em;padding:10px;">
|
| | | <i class="fa fa-key"></i>
|
| | | </div>
|
| | | <div style="display:inline-block;">
|
| | | <div wicket:id="comment" style="font-weight:bold;"></div>
|
| | | <pre wicket:id="fingerprint"></pre>
|
| | | </div>
|
| | | |
| | | <div style="display:inline-block;padding: 0px 20px">
|
| | | <div wicket:id="permission" style="font-weight:bold;"></div>
|
| | | <div wicket:id="algorithm"></div>
|
| | | </div>
|
| | | |
| | | <div style="display:inline-block;vertical-align:text-bottom;">
|
| | | <button class="btn btn-danger" wicket:id="delete"><wicket:message key="gb.delete"></wicket:message></button>
|
| | | </div>
|
| | | |
| | | <hr />
|
| | | </div>
|
| | | |
| | | <div class="well">
|
| | | <form wicket:id="addKeyForm">
|
| | | <h4><wicket:message key="gb.addSshKey"></wicket:message></h4>
|
| | | <div wicket:id="addKeyData"></div>
|
| | | <div wicket:id="addKeyPermission"></div>
|
| | | <div wicket:id="addKeyComment"></div>
|
| | | |
| | | <div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Add" wicket:message="value:gb.add" wicket:id="addKeyButton" /></div>
|
| | | </form>
|
| | | </div>
|
| | | </wicket:panel>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.panels;
|
| | |
|
| | | import java.util.ArrayList;
|
| | | import java.util.Arrays;
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.ajax.AjaxRequestTarget;
|
| | | import org.apache.wicket.ajax.markup.html.AjaxLink;
|
| | | import org.apache.wicket.ajax.markup.html.form.AjaxButton;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.Form;
|
| | | import org.apache.wicket.markup.repeater.Item;
|
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | |
|
| | | import com.gitblit.Constants.AccessPermission;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.transport.ssh.SshKey;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | |
|
| | |
|
| | | /**
|
| | | * A panel that enumerates and manages SSH public keys using AJAX.
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class SshKeysPanel extends BasePanel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | private final UserModel user;
|
| | |
|
| | | public SshKeysPanel(String wicketId, UserModel user) {
|
| | | super(wicketId);
|
| | |
|
| | | this.user = user;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void onInitialize() {
|
| | | super.onInitialize();
|
| | |
|
| | | setOutputMarkupId(true);
|
| | |
|
| | | final List<SshKey> keys = new ArrayList<SshKey>(app().keys().getKeys(user.username));
|
| | | final ListDataProvider<SshKey> dp = new ListDataProvider<SshKey>(keys);
|
| | | final DataView<SshKey> keysView = new DataView<SshKey>("keys", dp) {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void populateItem(final Item<SshKey> item) {
|
| | | final SshKey key = item.getModelObject();
|
| | | item.add(new Label("comment", key.getComment()));
|
| | | item.add(new Label("fingerprint", key.getFingerprint()));
|
| | | item.add(new Label("permission", key.getPermission().toString()));
|
| | | item.add(new Label("algorithm", key.getAlgorithm()));
|
| | |
|
| | | AjaxLink<Void> delete = new AjaxLink<Void>("delete") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void onClick(AjaxRequestTarget target) {
|
| | | if (app().keys().removeKey(user.username, key)) {
|
| | | // reset the keys list
|
| | | keys.clear();
|
| | | keys.addAll(app().keys().getKeys(user.username));
|
| | |
|
| | | // update the panel
|
| | | target.addComponent(SshKeysPanel.this);
|
| | | }
|
| | | }
|
| | | };
|
| | | item.add(delete);
|
| | | }
|
| | | };
|
| | | add(keysView);
|
| | |
|
| | | Form<Void> addKeyForm = new Form<Void>("addKeyForm");
|
| | |
|
| | | final IModel<String> keyData = Model.of("");
|
| | | addKeyForm.add(new TextAreaOption("addKeyData",
|
| | | getString("gb.key"),
|
| | | null,
|
| | | "span5",
|
| | | keyData));
|
| | |
|
| | | final IModel<AccessPermission> keyPermission = Model.of(AccessPermission.PUSH);
|
| | | addKeyForm.add(new ChoiceOption<AccessPermission>("addKeyPermission",
|
| | | getString("gb.permission"),
|
| | | getString("gb.sshKeyPermissionDescription"),
|
| | | keyPermission,
|
| | | Arrays.asList(AccessPermission.SSHPERMISSIONS)));
|
| | |
|
| | | final IModel<String> keyComment = Model.of("");
|
| | | addKeyForm.add(new TextOption("addKeyComment",
|
| | | getString("gb.comment"),
|
| | | getString("gb.sshKeyCommentDescription"),
|
| | | "span5",
|
| | | keyComment));
|
| | |
|
| | | addKeyForm.add(new AjaxButton("addKeyButton") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
|
| | |
|
| | | UserModel user = GitBlitWebSession.get().getUser();
|
| | | String data = keyData.getObject();
|
| | | if (StringUtils.isEmpty(data)) {
|
| | | // do not submit empty key
|
| | | return;
|
| | | }
|
| | |
|
| | | SshKey key = new SshKey(data);
|
| | | try {
|
| | | key.getPublicKey();
|
| | | } catch (Exception e) {
|
| | | // failed to parse the key
|
| | | return;
|
| | | }
|
| | |
|
| | | AccessPermission permission = keyPermission.getObject();
|
| | | key.setPermission(permission);
|
| | |
|
| | | String comment = keyComment.getObject();
|
| | | if (!StringUtils.isEmpty(comment)) {
|
| | | key.setComment(comment);
|
| | | }
|
| | |
|
| | | if (app().keys().addKey(user.username, key)) {
|
| | | // reset add key fields
|
| | | keyData.setObject("");
|
| | | keyPermission.setObject(AccessPermission.PUSH);
|
| | | keyComment.setObject("");
|
| | |
|
| | | // reset the keys list
|
| | | keys.clear();
|
| | | keys.addAll(app().keys().getKeys(user.username));
|
| | |
|
| | | // update the panel
|
| | | target.addComponent(SshKeysPanel.this);
|
| | | }
|
| | | }
|
| | | });
|
| | |
|
| | | add(addKeyForm);
|
| | | }
|
| | | }
|
| | |
| | |
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.RequestCycle;
|
| | | import org.apache.wicket.markup.html.WebPage;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.apache.wicket.markup.repeater.Item;
|
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | |
| | | import org.eclipse.jgit.lib.Repository;
|
| | |
|
| | | import com.gitblit.models.RefModel;
|
| | | import com.gitblit.servlet.RawServlet;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.pages.BlobPage;
|
| | | import com.gitblit.wicket.pages.CommitPage;
|
| | | import com.gitblit.wicket.pages.LogPage;
|
| | | import com.gitblit.wicket.pages.RawPage;
|
| | | import com.gitblit.wicket.pages.TagPage;
|
| | | import com.gitblit.wicket.pages.TagsPage;
|
| | | import com.gitblit.wicket.pages.TreePage;
|
| | |
| | | .newObjectParameter(repositoryName, entry.getReferencedObjectId()
|
| | | .getName())));
|
| | |
|
| | | fragment.add(new BookmarkablePageLink<Void>("raw", RawPage.class, WicketUtils
|
| | | .newObjectParameter(repositoryName, entry.getReferencedObjectId()
|
| | | .getName())));
|
| | | String contextUrl = RequestCycle.get().getRequest().getRelativePathPrefixToContextRoot();
|
| | | String rawUrl = RawServlet.asLink(contextUrl, repositoryName, entry.displayName,
|
| | | entry.getReferencedObjectId().getName());
|
| | | fragment.add(new ExternalLink("raw", rawUrl));
|
| | | item.add(fragment);
|
| | | } else {
|
| | | // TODO Tree Tag Object
|
New file |
| | |
| | | <!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:panel>
|
| | | <div style="padding-top:4px;">
|
| | | <div style="margin-bottom:1px;">
|
| | | <b><span wicket:id="name"></span></b>
|
| | | </div>
|
| | | <label class="checkbox" style="color:#777;"> <span wicket:id="description"></span>
|
| | | <p style="padding-top:5px;"><textarea rows="12" class="span5" wicket:id="text"></textarea></p>
|
| | | </label>
|
| | | |
| | | </div>
|
| | | </wicket:panel>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.panels;
|
| | |
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.TextArea;
|
| | | import org.apache.wicket.model.IModel;
|
| | |
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | |
|
| | | /**
|
| | | * A re-usable textarea option panel.
|
| | | *
|
| | | * title
|
| | | * description
|
| | | * [text
|
| | | * area]
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class TextAreaOption extends BasePanel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public TextAreaOption(String wicketId, String title, String description, IModel<String> model) {
|
| | | this(wicketId, title, description, null, model);
|
| | | }
|
| | |
|
| | | public TextAreaOption(String wicketId, String title, String description, String css, IModel<String> model) {
|
| | | super(wicketId);
|
| | | add(new Label("name", title));
|
| | | add(new Label("description", description).setVisible(!StringUtils.isEmpty(description)));
|
| | | TextArea<String> tf = new TextArea<String>("text", model);
|
| | | if (!StringUtils.isEmpty(css)) {
|
| | | WicketUtils.setCssClass(tf, css);
|
| | | }
|
| | | add(tf);
|
| | | }
|
| | | }
|
New file |
| | |
| | | <!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:panel>
|
| | | <div style="padding-top:4px;">
|
| | | <div style="margin-bottom:1px;">
|
| | | <b><span wicket:id="name"></span></b>
|
| | | </div>
|
| | | <label class="checkbox" style="color:#777;"> <span wicket:id="description"></span>
|
| | | <p style="padding-top:5px;"><input class="span3" type="text" wicket:id="text" /></p>
|
| | | </label>
|
| | | |
| | | </div>
|
| | | </wicket:panel>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.panels;
|
| | |
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.model.IModel;
|
| | |
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | |
|
| | | /**
|
| | | * A re-usable textfield option panel.
|
| | | *
|
| | | * title
|
| | | * description
|
| | | * [textfield]
|
| | | *
|
| | | * @author James Moger
|
| | | *
|
| | | */
|
| | | public class TextOption extends BasePanel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public TextOption(String wicketId, String title, String description, IModel<String> model) {
|
| | | this(wicketId, title, description, null, model);
|
| | | }
|
| | |
|
| | | public TextOption(String wicketId, String title, String description, String css, IModel<String> model) {
|
| | | super(wicketId);
|
| | | add(new Label("name", title));
|
| | | add(new Label("description", description).setVisible(!StringUtils.isEmpty(description)));
|
| | | TextField<String> tf = new TextField<String>("text", model);
|
| | | if (!StringUtils.isEmpty(css)) {
|
| | | WicketUtils.setCssClass(tf, css);
|
| | | }
|
| | | add(tf);
|
| | | }
|
| | | }
|
New file |
| | |
| | | <!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:panel>
|
| | | <table class="table tickets"> |
| | | <tbody>
|
| | | <tr wicket:id="row">
|
| | | <td class="ticket-list-icon">
|
| | | <i wicket:id="state"></i>
|
| | | </td>
|
| | | <td>
|
| | | <span wicket:id="title">[title]</span> <span wicket:id="labels" style="font-weight: normal;color:white;"><span class="label" wicket:id="label"></span></span>
|
| | | <div class="ticket-list-details">
|
| | | <span style="padding-right: 10px;" class="hidden-phone">
|
| | | <wicket:message key="gb.createdBy"></wicket:message>
|
| | | <span style="padding: 0px 2px" wicket:id="createdBy">[createdBy]</span> <span class="date" wicket:id="createDate">[create date]</span>
|
| | | </span>
|
| | | <span wicket:id="indicators" style="white-space:nowrap;"><i wicket:id="icon"></i> <span style="padding-right:10px;" wicket:id="count"></span></span>
|
| | | </div>
|
| | | <div class="hidden-phone" wicket:id="updated"></div>
|
| | | <div class="ticket-list-details"><span class="activitySwatch" wicket:id="ticketsLink">[tickets link]</span></div>
|
| | | </td>
|
| | | <td class="ticket-list-state">
|
| | | <span class="badge badge-info" wicket:id="votes"></span>
|
| | | </td>
|
| | | <td class="hidden-phone ticket-list-state">
|
| | | <i wicket:message="title:gb.watching" style="color:#888;" class="fa fa-eye" wicket:id="watching"></i>
|
| | | </td>
|
| | | <td class="ticket-list-state">
|
| | | <div wicket:id="status"></div>
|
| | | </td>
|
| | | <td class="indicators">
|
| | | <div> |
| | | <b>#<span wicket:id="id">[id]</span></b>
|
| | | </div>
|
| | | <div wicket:id="responsible"></div>
|
| | | </td>
|
| | | </tr>
|
| | | </tbody>
|
| | | </table>
|
| | |
|
| | | <wicket:fragment wicket:id="updatedFragment">
|
| | | <div class="ticket-list-details">
|
| | | <wicket:message key="gb.updatedBy"></wicket:message>
|
| | | <span style="padding: 0px 2px" wicket:id="updatedBy">[updatedBy]</span> <span class="date" wicket:id="updateDate">[update date]</span>
|
| | | </div>
|
| | | </wicket:fragment>
|
| | |
|
| | | </wicket:panel>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.wicket.panels; |
| | | |
| | | import java.text.MessageFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | import org.apache.wicket.PageParameters; |
| | | import org.apache.wicket.behavior.SimpleAttributeModifier; |
| | | import org.apache.wicket.markup.html.basic.Label; |
| | | import org.apache.wicket.markup.html.panel.Fragment; |
| | | import org.apache.wicket.markup.repeater.Item; |
| | | import org.apache.wicket.markup.repeater.data.DataView; |
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider; |
| | | import org.eclipse.jgit.lib.Repository; |
| | | |
| | | import com.gitblit.Constants; |
| | | import com.gitblit.models.RepositoryModel; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.tickets.QueryResult; |
| | | import com.gitblit.tickets.TicketLabel; |
| | | import com.gitblit.utils.ArrayUtils; |
| | | import com.gitblit.utils.BugtraqProcessor; |
| | | import com.gitblit.utils.StringUtils; |
| | | import com.gitblit.wicket.GitBlitWebSession; |
| | | import com.gitblit.wicket.TicketsUI; |
| | | import com.gitblit.wicket.TicketsUI.Indicator; |
| | | import com.gitblit.wicket.WicketUtils; |
| | | import com.gitblit.wicket.pages.TicketsPage; |
| | | import com.gitblit.wicket.pages.UserPage; |
| | | |
| | | /** |
| | | * |
| | | * The ticket list panel lists tickets in a table. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public class TicketListPanel extends BasePanel { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public TicketListPanel(String wicketId, List<QueryResult> list, final boolean showSwatch, final boolean showRepository) { |
| | | super(wicketId); |
| | | |
| | | final ListDataProvider<QueryResult> dp = new ListDataProvider<QueryResult>(list); |
| | | DataView<QueryResult> dataView = new DataView<QueryResult>("row", dp) { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | protected void populateItem(Item<QueryResult> item) { |
| | | final QueryResult ticket = item.getModelObject(); |
| | | final RepositoryModel repository = app().repositories().getRepositoryModel(ticket.repository); |
| | | |
| | | if (showSwatch) { |
| | | // set repository color |
| | | String color = StringUtils.getColor(StringUtils.stripDotGit(repository.name)); |
| | | WicketUtils.setCssStyle(item, MessageFormat.format("border-left: 2px solid {0};", color)); |
| | | } |
| | | |
| | | PageParameters tp = WicketUtils.newObjectParameter(ticket.repository, "" + ticket.number); |
| | | |
| | | if (showRepository) { |
| | | String name = StringUtils.stripDotGit(ticket.repository); |
| | | PageParameters rp = WicketUtils.newOpenTicketsParameter(ticket.repository); |
| | | LinkPanel link = new LinkPanel("ticketsLink", null, name, TicketsPage.class, rp); |
| | | WicketUtils.setCssBackground(link, name); |
| | | item.add(link); |
| | | } else { |
| | | item.add(new Label("ticketsLink").setVisible(false)); |
| | | } |
| | | |
| | | item.add(TicketsUI.getStateIcon("state", ticket.type, ticket.status)); |
| | | item.add(new Label("id", "" + ticket.number)); |
| | | UserModel creator = app().users().getUserModel(ticket.createdBy); |
| | | if (creator != null) { |
| | | item.add(new LinkPanel("createdBy", null, creator.getDisplayName(), |
| | | UserPage.class, WicketUtils.newUsernameParameter(ticket.createdBy))); |
| | | } else { |
| | | item.add(new Label("createdBy", ticket.createdBy)); |
| | | } |
| | | item.add(WicketUtils.createDateLabel("createDate", ticket.createdAt, GitBlitWebSession |
| | | .get().getTimezone(), getTimeUtils(), false)); |
| | | |
| | | if (ticket.updatedAt == null) { |
| | | item.add(new Label("updated").setVisible(false)); |
| | | } else { |
| | | Fragment updated = new Fragment("updated", "updatedFragment", this); |
| | | UserModel updater = app().users().getUserModel(ticket.updatedBy); |
| | | if (updater != null) { |
| | | updated.add(new LinkPanel("updatedBy", null, updater.getDisplayName(), |
| | | UserPage.class, WicketUtils.newUsernameParameter(ticket.updatedBy))); |
| | | } else { |
| | | updated.add(new Label("updatedBy", ticket.updatedBy)); |
| | | } |
| | | updated.add(WicketUtils.createDateLabel("updateDate", ticket.updatedAt, GitBlitWebSession |
| | | .get().getTimezone(), getTimeUtils(), false)); |
| | | item.add(updated); |
| | | } |
| | | |
| | | item.add(new LinkPanel("title", "list subject", StringUtils.trimString( |
| | | ticket.title, Constants.LEN_SHORTLOG), TicketsPage.class, tp)); |
| | | |
| | | ListDataProvider<String> labelsProvider = new ListDataProvider<String>(ticket.getLabels()); |
| | | DataView<String> labelsView = new DataView<String>("labels", labelsProvider) { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void populateItem(final Item<String> labelItem) { |
| | | BugtraqProcessor btp = new BugtraqProcessor(app().settings()); |
| | | Repository db = app().repositories().getRepository(repository.name); |
| | | String content = btp.processText(db, repository.name, labelItem.getModelObject()); |
| | | db.close(); |
| | | Label label = new Label("label", content); |
| | | label.setEscapeModelStrings(false); |
| | | TicketLabel tLabel = app().tickets().getLabel(repository, labelItem.getModelObject()); |
| | | String background = MessageFormat.format("background-color:{0};", tLabel.color); |
| | | label.add(new SimpleAttributeModifier("style", background)); |
| | | labelItem.add(label); |
| | | } |
| | | }; |
| | | item.add(labelsView); |
| | | |
| | | if (StringUtils.isEmpty(ticket.responsible)) { |
| | | item.add(new Label("responsible").setVisible(false)); |
| | | } else { |
| | | UserModel responsible = app().users().getUserModel(ticket.responsible); |
| | | if (responsible == null) { |
| | | responsible = new UserModel(ticket.responsible); |
| | | } |
| | | GravatarImage avatar = new GravatarImage("responsible", responsible.getDisplayName(), |
| | | responsible.emailAddress, null, 16, true); |
| | | avatar.setTooltip(getString("gb.responsible") + ": " + responsible.getDisplayName()); |
| | | item.add(avatar); |
| | | } |
| | | |
| | | // votes indicator |
| | | Label v = new Label("votes", "" + ticket.votesCount); |
| | | WicketUtils.setHtmlTooltip(v, getString("gb.votes")); |
| | | item.add(v.setVisible(ticket.votesCount > 0)); |
| | | |
| | | // watching indicator |
| | | item.add(new Label("watching").setVisible(ticket.isWatching(GitBlitWebSession.get().getUsername()))); |
| | | |
| | | // status indicator |
| | | String css = TicketsUI.getLozengeClass(ticket.status, true); |
| | | Label l = new Label("status", ticket.status.toString()); |
| | | WicketUtils.setCssClass(l, css); |
| | | item.add(l); |
| | | |
| | | // add the ticket indicators/icons |
| | | List<Indicator> indicators = new ArrayList<Indicator>(); |
| | | |
| | | // comments |
| | | if (ticket.commentsCount > 0) { |
| | | int count = ticket.commentsCount; |
| | | String pattern = getString("gb.nComments"); |
| | | if (count == 1) { |
| | | pattern = getString("gb.oneComment"); |
| | | } |
| | | indicators.add(new Indicator("fa fa-comment", count, pattern)); |
| | | } |
| | | |
| | | // participants |
| | | if (!ArrayUtils.isEmpty(ticket.participants)) { |
| | | int count = ticket.participants.size(); |
| | | if (count > 1) { |
| | | String pattern = getString("gb.nParticipants"); |
| | | indicators.add(new Indicator("fa fa-user", count, pattern)); |
| | | } |
| | | } |
| | | |
| | | // attachments |
| | | if (!ArrayUtils.isEmpty(ticket.attachments)) { |
| | | int count = ticket.attachments.size(); |
| | | String pattern = getString("gb.nAttachments"); |
| | | if (count == 1) { |
| | | pattern = getString("gb.oneAttachment"); |
| | | } |
| | | indicators.add(new Indicator("fa fa-file", count, pattern)); |
| | | } |
| | | |
| | | // patchset revisions |
| | | if (ticket.patchset != null) { |
| | | int count = ticket.patchset.commits; |
| | | String pattern = getString("gb.nCommits"); |
| | | if (count == 1) { |
| | | pattern = getString("gb.oneCommit"); |
| | | } |
| | | indicators.add(new Indicator("fa fa-code", count, pattern)); |
| | | } |
| | | |
| | | // milestone |
| | | if (!StringUtils.isEmpty(ticket.milestone)) { |
| | | indicators.add(new Indicator("fa fa-bullseye", ticket.milestone)); |
| | | } |
| | | |
| | | ListDataProvider<Indicator> indicatorsDp = new ListDataProvider<Indicator>(indicators); |
| | | DataView<Indicator> indicatorsView = new DataView<Indicator>("indicators", indicatorsDp) { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void populateItem(final Item<Indicator> item) { |
| | | Indicator indicator = item.getModelObject(); |
| | | String tooltip = indicator.getTooltip(); |
| | | |
| | | Label icon = new Label("icon"); |
| | | WicketUtils.setCssClass(icon, indicator.css); |
| | | item.add(icon); |
| | | |
| | | if (indicator.count > 0) { |
| | | Label count = new Label("count", "" + indicator.count); |
| | | item.add(count.setVisible(!StringUtils.isEmpty(tooltip))); |
| | | } else { |
| | | item.add(new Label("count").setVisible(false)); |
| | | } |
| | | |
| | | WicketUtils.setHtmlTooltip(item, tooltip); |
| | | } |
| | | }; |
| | | item.add(indicatorsView); |
| | | } |
| | | }; |
| | | |
| | | add(dataView); |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | /* |
| | | * Copyright 2014 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.wicket.panels; |
| | | |
| | | import java.io.Serializable; |
| | | import java.text.MessageFormat; |
| | | |
| | | import org.apache.wicket.PageParameters; |
| | | import org.apache.wicket.markup.html.form.TextField; |
| | | import org.apache.wicket.model.IModel; |
| | | import org.apache.wicket.model.Model; |
| | | import org.apache.wicket.request.target.basic.RedirectRequestTarget; |
| | | |
| | | import com.gitblit.utils.StringUtils; |
| | | import com.gitblit.wicket.SessionlessForm; |
| | | import com.gitblit.wicket.WicketUtils; |
| | | import com.gitblit.wicket.pages.BasePage; |
| | | |
| | | public class TicketSearchForm extends SessionlessForm<Void> implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private final String repositoryName; |
| | | |
| | | private final IModel<String> searchBoxModel; |
| | | |
| | | public TicketSearchForm(String id, String repositoryName, String text, |
| | | Class<? extends BasePage> pageClass, PageParameters params) { |
| | | |
| | | super(id, pageClass, params); |
| | | |
| | | this.repositoryName = repositoryName; |
| | | this.searchBoxModel = new Model<String>(text == null ? "" : text); |
| | | |
| | | TextField<String> searchBox = new TextField<String>("ticketSearchBox", searchBoxModel); |
| | | add(searchBox); |
| | | } |
| | | |
| | | @Override |
| | | protected |
| | | void onInitialize() { |
| | | super.onInitialize(); |
| | | WicketUtils.setHtmlTooltip(get("ticketSearchBox"), |
| | | MessageFormat.format(getString("gb.searchTicketsTooltip"), "")); |
| | | WicketUtils.setInputPlaceholder(get("ticketSearchBox"), getString("gb.searchTickets")); |
| | | } |
| | | |
| | | @Override |
| | | public void onSubmit() { |
| | | String searchString = searchBoxModel.getObject(); |
| | | if (StringUtils.isEmpty(searchString)) { |
| | | // redirect to self to avoid wicket page update bug |
| | | String absoluteUrl = getAbsoluteUrl(); |
| | | getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl)); |
| | | return; |
| | | } |
| | | |
| | | // use an absolute url to workaround Wicket-Tomcat problems with |
| | | // mounted url parameters (issue-111) |
| | | PageParameters params = WicketUtils.newRepositoryParameter(repositoryName); |
| | | params.add("s", searchString); |
| | | String absoluteUrl = getAbsoluteUrl(pageClass, params); |
| | | getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl)); |
| | | } |
| | | } |
New file |
| | |
| | | <!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:panel>
|
| | | <div style="display:inline-block;vertical-align:top;padding: 0px 2px 2px;"><img wicket:id="userGravatar"></img></div>
|
| | | <div style="display:inline-block;">
|
| | | <div style="font-size:1.5em;" wicket:id="userDisplayName"></div>
|
| | | <div style="color:#888;font-size:1.2em;padding-top:4px;"><span wicket:id="userTitle"></span></div>
|
| | | </div>
|
| | | </wicket:panel>
|
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2014 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.wicket.panels;
|
| | |
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | |
|
| | | import com.gitblit.models.UserModel;
|
| | |
|
| | | public class UserTitlePanel extends BasePanel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public UserTitlePanel(String wicketId, UserModel user, String title) {
|
| | | super(wicketId);
|
| | | add(new GravatarImage("userGravatar", user, "gravatar", 36, false));
|
| | | add(new Label("userDisplayName", user.getDisplayName()));
|
| | | add(new Label("userTitle", title));
|
| | | }
|
| | | }
|
New file |
| | |
| | | ## Bitte melden Sie sich an
|
| | |
|
| | | Bitte geben Sie Ihre Zugangsdaten ein um auf Gitblit zuzugreifen.
|
New file |
| | |
| | | ## Login richiesto
|
| | |
|
| | | Per favore fornisci le tue credenziali per accedere a questo sito Gitblit.
|
| | |
|
| | |
| | | # fetch all current ticket patchsets |
| | | print("Fetching ticket patchsets from the '{}' repository".format(args.remote)) |
| | | if args.quiet: |
| | | __call(['git', 'fetch', args.remote, '--quiet']) |
| | | __call(['git', 'fetch', '-p', args.remote, '--quiet']) |
| | | else: |
| | | __call(['git', 'fetch', args.remote]) |
| | | __call(['git', 'fetch', '-p', args.remote]) |
| | | else: |
| | | # fetch specific patchset |
| | | __resolve_patchset(args) |
| | |
| | | branches.append(branch.strip()) |
| | | |
| | | branch = 'topic/' + args.topic |
| | | try: |
| | | int(args.topic) |
| | | branch = 'ticket/' + args.topic |
| | | except ValueError: |
| | | pass |
| | | |
| | | illegals = set(branches) & {'topic', branch} |
| | | |
| | | # ensure there are no local branch names that will interfere with branch creation |
| | |
| | | curr_branch = branch[1:].strip() |
| | | if curr_branch.startswith('topic/'): |
| | | topic = curr_branch[6:].strip() |
| | | try: |
| | | int(topic) |
| | | push_ref = topic |
| | | except ValueError: |
| | | pass |
| | | if curr_branch.startswith('ticket/'): |
| | | topic = curr_branch[7:].strip() |
| | | try: |
| | | int(topic) |
| | | push_ref = topic |
| | |
| | | if fields[0] == 'remote' and fields[1].strip().startswith('--> #'): |
| | | # set the upstream branch configuration |
| | | args.id = int(fields[1].strip()[len('--> #'):]) |
| | | __call(['git', 'fetch', args.remote]) |
| | | __call(['git', 'branch', '--set-upstream-to={}/ticket/{:d}'.format(args.remote, args.id)]) |
| | | __call(['git', 'fetch', '-p', args.remote]) |
| | | __call(['git', 'branch', '-u', '{}/ticket/{:d}'.format(args.remote, args.id)]) |
| | | break |
| | | |
| | | return |
New file |
| | |
| | | ## Willkommen bei Gitblit
|
| | |
|
| | | Eine schnelle und einfache Art und Weise Ihre eigenen [Git](http://www.git-scm.com) Repositories zu hosten.
|
New file |
| | |
| | | ## Benvenuto su Gitblit
|
| | |
|
| | | Un modo facile e veloce per ospitare o visualizzare i tuoi repository [Git](http://www.git-scm.com).
|
| | |
| | | - Customizable regular expression substitution for commit messages (i.e. bug or code review link integration)
|
| | | - Single text file for users configuration
|
| | | - Translations
|
| | | - English
|
| | | - Japanese
|
| | | - Spanish
|
| | | - Polish
|
| | | - Korean
|
| | | - Brazilian Portuguese
|
| | | - Dutch
|
| | | - German (de)
|
| | | - English (en)
|
| | | - Spanish (es)
|
| | | - French (fr)
|
| | | - Italian (it)
|
| | | - Japanese (ja)
|
| | | - Korean (ko)
|
| | | - Dutch (nl)
|
| | | - Norwegian (no)
|
| | | - Polish (pl)
|
| | | - Brazilian Portuguese (pt_BR)
|
| | | - Simplified Chinese (zh_CN)
|
| | | - French
|
| | |
|
| | | ## Gitblit GO Features
|
| | | - Out-of-the-box integrated stack requiring minimal configuration
|
| | |
| | | public void onUninstall() { |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * You can also create Webapp plugins that register pages. |
| | | */ |
| | | public class ExampleWicketPlugin extends GitblitWicketPlugin { |
| | | @Override |
| | | public void start() { |
| | | } |
| | | |
| | | @Override |
| | | public void stop() { |
| | | } |
| | | |
| | | @Override |
| | | public void onInstall() { |
| | | } |
| | | |
| | | @Override |
| | | public void onUpgrade(Version oldVersion) { |
| | | } |
| | | |
| | | @Override |
| | | public void onUninstall() { |
| | | } |
| | | |
| | | @Override |
| | | protected void init(GitblitWicketApp app) { |
| | | app.mount("/logo", LogoPage.class); |
| | | app.mount("/hello", HelloWorldPage.class); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### SSH Dispatch Command |
| | |
| | | import org.kohsuke.args4j.Option; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.transport.ssh.commands.CommandMetaData; |
| | | import com.gitblit.transport.ssh.commands.DispatchCommand; |
| | | import com.gitblit.transport.ssh.commands.UsageExample; |
| | |
| | | } |
| | | ``` |
| | | |
| | | ### Request Filter |
| | | |
| | | *SINCE 1.6.0* |
| | | |
| | | You can provide your own custom request filter by subclassing the *HttpRequestFilter* class. |
| | | |
| | | ```java |
| | | import com.gitblit.extensions.HttpRequestFilter; |
| | | import ro.fortsoft.pf4j.Extension; |
| | | |
| | | @Extension |
| | | public class MyRequestFilter extends HttpRequestFilter { |
| | | |
| | | @Override |
| | | public void doFilter(ServletRequest request, ServletResponse response, |
| | | FilterChain chain) throws IOException, ServletException { |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### User Menu Items |
| | | |
| | | *SINCE 1.6.0* |
| | | |
| | | You can provide your own user menu items by subclassing the *UserMenuExtension* class. |
| | | |
| | | ```java |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import ro.fortsoft.pf4j.Extension; |
| | | import com.gitblit.extensions.UserMenuExtension; |
| | | import com.gitblit.models.Menu.ExternalLinkMenuItem; |
| | | import com.gitblit.models.Menu.MenuItem; |
| | | import com.gitblit.models.UserModel; |
| | | |
| | | @Extension |
| | | public class MyUserMenuContributor extends UserMenuExtension { |
| | | |
| | | @Override |
| | | public List<MenuItem> getMenuItems(UserModel user) { |
| | | MenuItem item = new ExternalLinkMenuItem("Github", String.format("https://github.com/%s", user.username)); |
| | | return Arrays.asList(item); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### Navigation Links |
| | | |
| | | *SINCE 1.6.0* |
| | | |
| | | You can provide your own top-level navigation links by subclassing the *NavLinkExtension* class. |
| | | |
| | | ```java |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import ro.fortsoft.pf4j.Extension; |
| | | import com.gitblit.extensions.NavLinkExtension; |
| | | import com.gitblit.models.UserModel; |
| | | |
| | | @Extension |
| | | public class MyNavLink extends NavLinkExtension { |
| | | |
| | | @Override |
| | | public List<NavLink> getNavLinks(UserModel user) { |
| | | NavLink link = new ExternalLinkMenuItem("Github", String.format("https://github.com/%s", user.username)); |
| | | return Arrays.asList(link); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### Server Lifecycle Listener |
| | | |
| | | *SINCE 1.6.0* |
| | | |
| | | You can provide a lifecycle listener to be notified when Gitblit has completely started and just before Gitblit is gracefully terminated. |
| | | |
| | | ```java |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import ro.fortsoft.pf4j.Extension; |
| | | import com.gitblit.extensions.LifeCycleListener; |
| | | |
| | | @Extension |
| | | public class MyLifeCycleListener extends LifeCycleListener { |
| | | |
| | | final Logger log = LoggerFactory.getLogger(getClass()); |
| | | |
| | | @Override |
| | | public void onStartup() { |
| | | log.info("Gitblit is Ready!!"); |
| | | } |
| | | |
| | | @Override |
| | | public void onShutdown() { |
| | | log.info("Gitblit is Going Down!!"); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### Repository Lifecycle Listener |
| | | |
| | | *SINCE 1.6.0* |
| | | |
| | | You can provide a lifecycle listener to be notified when Gitblit has created or deleted a repository. |
| | | |
| | | ```java |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import ro.fortsoft.pf4j.Extension; |
| | | import com.gitblit.extensions.RepositoryLifeCycleListener; |
| | | import com.gitblit.models.RepositoryModel; |
| | | |
| | | @Extension |
| | | public class MyRepoLifeCycleListener extends RepositoryLifeCycleListener { |
| | | |
| | | final Logger log = LoggerFactory.getLogger(getClass()); |
| | | |
| | | @Override |
| | | public void onCreation(RepositoryModel repo) { |
| | | log.info("Gitblit created {}", repo); |
| | | } |
| | | |
| | | @Override |
| | | public void onDeletion(RepositoryModel repo) { |
| | | log.info("Gitblit deleted {}", repo); |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### User/Team Lifecycle Listener |
| | | |
| | | *SINCE 1.6.0* |
| | | |
| | | You can provide a lifecycle listener to be notified when Gitblit has created or deleted a user or a team. |
| | | |
| | | ```java |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import ro.fortsoft.pf4j.Extension; |
| | | import com.gitblit.extensions.UserTeamLifeCycleListener; |
| | | import com.gitblit.models.TeamModel; |
| | | import com.gitblit.models.UserModel; |
| | | |
| | | @Extension |
| | | public class MyUserTeamLifeCycleListener extends UserTeamLifeCycleListener { |
| | | |
| | | final Logger log = LoggerFactory.getLogger(getClass()); |
| | | |
| | | @Override |
| | | public void onCreation(UserModel user) { |
| | | log.info("Gitblit created user {}", user); |
| | | } |
| | | |
| | | @Override |
| | | public void onDeletion(UserModel user) { |
| | | log.info("Gitblit deleted user {}", user); |
| | | } |
| | | |
| | | @Override |
| | | public void onCreation(TeamModel team) { |
| | | log.info("Gitblit created team {}", team); |
| | | } |
| | | |
| | | @Override |
| | | public void onDeletion(TeamModel team) { |
| | | log.info("Gitblit deleted team {}", team); |
| | | } |
| | | } |
| | | ``` |
| | |
| | | |
| | | Through this command interface plugins can be started, stopped, disabled, enabled, installed, uninstalled, listed, etc. Each command is supports the `--help` argument which will guide you in understanding the options and usage of the command. |
| | | |
| | | You may watch an Asciinema screencast of how to use the SSH transport and the plugin manager [here](https://asciinema.org/a/9342). |
| | | |
| | | ### Default Plugin Registry |
| | | |
| | | Gitblit provides a simple default registry of plugins. The registry is a JSON file and it lists plugin metadata and download locations. |
| | | |
| | | plugins.registry = http://plugins.gitblit.com/plugins.json |
| | | |
| | | The [registry](http://plugins.gitblit.com/plugins.json) is currently hosted in a [Git repository on Github](https://github.com/gitblit/gitblit-registry). This git repository is also a [Maven-compatible repository](http://plugins.gitblit.com), which hosts some plugin binaries. |
| | | The [default plugins registry](http://plugins.gitblit.com) is currently hosted in a [Git repository on Github](https://github.com/gitblit/gitblit-registry). You can view the default registry file [here](http://plugins.gitblit.com/plugins.json). The default plugin registry is also a Maven-2 compatible repository. |
| | | |
| | | ### Contributing Plugins to the Default Registry |
| | | |
| | |
| | | The `plugins.json` file is parameterized with the `${self}` placeholder. This parameter is substituted on download with with the source URL of the registry file. This allows you to clone and serve your own copy of this git repository or just serve your own `plugins.json` on your own network. |
| | | |
| | | Gitblit also supports loading multiple plugin registries. Just place another **properly formatted** `.json` file in `${baseFolder}/plugins` and Gitblit will load that as an additional registry. |
| | | |
| | | ### Mac OSX Fonts |
| | | |
| | | Gitblit's core SSH commands and those in the *powertools* plugin rely on ANSI border characters to provide a pretty presentation of data. Unfortunately, the fonts provided by Apple - while very nice - don't work well with ANSI border characters. The following public domain fixed-width, fixed-point, bitmapped fonts work very nicely. I find the 6x12 font with a line spacing of ~0.8 to be quite acceptable. |
| | | |
| | | [6x12.dfont](6x12.dfont) |
| | | [6x13.dfont](6x13.dfont) |
| | | [7x13.dfont](7x13.dfont) |
| | | [7x14.dfont](7x14.dfont) |
| | | |
| | |
| | | This is not exactly a formal roadmap but it is a priority list of what might be implemented in future releases.
|
| | | This list is volatile and may not reflect what will be in the next release.
|
| | |
|
| | | * **In-Progress**: Integrate an SSH daemon (issue-369)
|
| | | * Diff should highlight inserted/removed fragment compared to original line
|
| | | * Respect Gerrit branch permissions, if found (issue 36)
|
| | |
|
| | | * Add support for Project owners/administrators (ticket-75)
|
| | | * Add Project create/update pages
|
| | | * Integrate improvements for git-flow (ticket-55)
|
| | |
| | | <tr><th>url parameter</th><th>default</th><th>description</th></tr>
|
| | | <tr><td colspan='3'><b>standard query</b></td></tr>
|
| | | <tr><td><em>repository</em></td><td><em>required</em></td><td>repository name is part of the url (see examples below)</td></tr>
|
| | | <tr><td>ot=</td><td><em>optional</em><br/>default: COMMIT</td><td>object type to return in results. COMMIT or TAG</td></tr>
|
| | | <tr><td>h=</td><td><em>optional</em><br/>default: HEAD</td><td>starting branch, ref, or commit id</td></tr>
|
| | | <tr><td>l=</td><td><em>optional</em><br/>default: web.syndicationEntries</td><td>maximum return count</td></tr>
|
| | | <tr><td>pg=</td><td><em>optional</em><br/>default: 0</td><td>page number for paging<br/>(offset into history = pagenumber*maximum return count)</td></tr>
|
| | |
| | | <tr><td>Gitblit v0.8.0</td><td>2</td></tr>
|
| | | <tr><td>Gitblit v0.9.0 - v1.0.0</td><td>3</td></tr>
|
| | | <tr><td>Gitblit v1.1.0</td><td>4</td></tr>
|
| | | <tr><td>Gitblit v1.2.0+</td><td>5</td></tr>
|
| | | <tr><td>Gitblit v1.3.1+</td><td>6</td></tr>
|
| | | <tr><td>Gitblit v1.4.0+</td><td>7</td></tr>
|
| | | <tr><td>Gitblit v1.2.0</td><td>5</td></tr>
|
| | | <tr><td>Gitblit v1.3.1</td><td>6</td></tr>
|
| | | <tr><td>Gitblit v1.4.0</td><td>7</td></tr>
|
| | | <tr><td>Gitblit v1.6.0</td><td>8</td></tr>
|
| | | </tbody>
|
| | | </table>
|
| | |
|
| | |
| | | <tr><td>LIST_BRANCHES</td><td>-</td><td>-</td><td>1</td><td>-</td><td>Map<String, List<String>></td></tr>
|
| | | <tr><td>LIST_SETTINGS</td><td>-</td><td><em>-</em></td><td>1</td><td>-</td><td>ServerSettings (basic keys)</td></tr>
|
| | | <tr><td>GET_USER</td><td>user name</td><td>-</td><td>6</td><td>-</td><td>UserModel</td></tr>
|
| | | <tr><td>FORK_REPOSITORY</td><td>repository name</td><td><em>-</em></td><td>8</td><td>-</td><td>-</td></tr>
|
| | | <tr><td colspan='6'><em>web.enableRpcManagement=true</em></td></tr>
|
| | | <tr><td>CREATE_REPOSITORY</td><td>repository name</td><td><em>admin</em></td><td>1</td><td>RepositoryModel</td><td>-</td></tr>
|
| | | <tr><td>EDIT_REPOSITORY</td><td>repository name</td><td><em>admin</em></td><td>1</td><td>RepositoryModel</td><td>-</td></tr>
|
| | |
| | |
|
| | | The SSH transport is a very exciting improvement to Gitblit. Aside from offering a simple password-less, public key workflow the SSH transport also allows exposes a new approach to interacting with Gitblit: SSH commands. The Gerrit and Android projects have to be thanked for providing great base SSH code that Gitblit has integrated.
|
| | |
|
| | | You may watch an Asciinema screencast of using the SSH transport and it's command infrastructure [here](https://asciinema.org/a/9342).
|
| | |
|
| | | ### Cloning & Pushing
|
| | |
|
| | | By default, Gitblit serves the SSH transport on port 29418, which is the same as Gerrit. Why was 29418 chosen? It's likely because it resembles the IANA port assigned to the git protocol (9418).
|
| | |
| | |
|
| | | ssh-keygen
|
| | |
|
| | | **NOTE:** It is important to note that *ssh-keygen* generates a public/private keypair (e.g. id_rsa and id_rsa.pub). You want to upload the *public* key, which is denoted by the *.pub* file extension.
|
| | |
|
| | | #### Uploading your public key from the command-line
|
| | |
|
| | | Then you can upload your *public* key right from the command-line.
|
| | |
|
| | | cat ~/.ssh/id_rsa.pub | ssh -l <username> -p 29418 <hostname> keys add
|
| | | cat c:\<userfolder>\.ssh\id_rsa.pub | ssh -l <username> -p 29418 <hostname> keys add
|
| | |
|
| | | **NOTE:** It is important to note that *ssh-keygen* generates a public/private keypair (e.g. id_rsa and id_rsa.pub). You want to upload the *public* key, which is denoted by the *.pub* file extension.
|
| | | #### Uploading your public key through the browser
|
| | |
|
| | | Once you've done both of those steps you should be able to execute the following command without a password prompt.
|
| | | 1. Navigate to your *profile* page from the dropdown user menu.
|
| | | 2. Click the *SSH Keys* tab and paste your public key into the *Add SSH Key* form.
|
| | | 3. Click the *Save* button
|
| | |
|
| | | Once you ave uploaded your public key you should be able to execute the following command without a password prompt.
|
| | |
|
| | | ssh -l <username> -p 29418 <hostname>
|
| | |
|
| | |
| | | | R | SSH key may be used to clone/fetch |
|
| | | | RW | SSH key may be used to clone/fetch and push |
|
| | |
|
| | | ### Mac OSX Fonts
|
| | |
|
| | | Many of Gitblit's SSH commands rely on ANSI border characters to provide a pretty presentation of data. Unfortunately, the fonts provided by Apple - while very nice - don't work well with ANSI border characters. The following public domain fixed-width, fixed-point, bitmapped fonts work very nicely. I find the 6x12 font with a line spacing of ~0.8 to be quite acceptable.
|
| | |
|
| | | [6x12.dfont](6x12.dfont)
|
| | | [6x13.dfont](6x13.dfont)
|
| | | [7x13.dfont](7x13.dfont)
|
| | | [7x14.dfont](7x14.dfont)
|
| | |
|
| | |
| | | <div class="well" style="margin-left:5px;float:right;width:275px;padding: 10px 10px;">
|
| | | <script>
|
| | | (function(d, s, id) {
|
| | | var js, fjs = d.getElementsByTagName(s)[0];
|
| | | if (d.getElementById(id)) return;
|
| | | js = d.createElement(s); js.id = id;
|
| | | js.async = true;
|
| | | js.src = "//go.jelastic.com/widgets.js";
|
| | | fjs.parentNode.insertBefore(js, fjs);
|
| | | }(document, 'script', 'jelastic-jssdk'));
|
| | | </script>
|
| | | <div style="text-align:center">
|
| | | <b>Current Release ${project.releaseVersion} (${project.releaseDate})</b><br/><a href="releasenotes.html">release notes</a>
|
| | | <div style="padding:5px;"><a style="width:175px;text-decoration:none;" class="btn btn-success" href="%GCURL%gitblit-${project.releaseVersion}.zip">Download Gitblit GO (Windows)</a></div>
|
| | | <div style="padding:5px;"><a style="width:175px;text-decoration:none;" class="btn btn-success" href="%GCURL%gitblit-${project.releaseVersion}.tar.gz">Download Gitblit GO (Linux/OSX)</a></div>
|
| | | <div style="padding:5px;"><a style="width:175px;text-decoration:none;" class="btn btn-danger" href="%GCURL%gitblit-${project.releaseVersion}.war">Download Gitblit WAR</a></div>
|
| | | <div style="padding:5px;"><a style="width:175px;text-decoration:none;" class="btn btn-info" href="%GCURL%express-${project.releaseVersion}.zip">Download Gitblit Express</a></div>
|
| | | <div style="padding:5px;"><a style="width:175px;text-decoration:none;" class="btn btn-primary" href="%GCURL%manager-${project.releaseVersion}.zip">Download Gitblit Manager</a></div>
|
| | | <a href='https://bintray.com/gitblit/releases/gitblit/view?source=watch' alt='Get automatic notifications about new "stable" versions'><img src='https://www.bintray.com/docs/images/bintray_badge_color.png'></a>
|
| | | </div>
|
| | |
|
| | | <div data-manifest="http://1c57d83a4c5f3a21ec25c050d4c5e37b.app.jelastic.com/xssu/cross/download/RDYYHABkAFJbUVlMMVU7RUtDARgATExFCEBuGS4jdQJKRUsEDwIBQmNTTEBI" data-width="280" data-theme="flat-blue" data-text="Get it hosted now!" data-tx-empty="Type your email and click the button" data-tx-invalid-email="Invalid email, please check the spelling" data-tx-error="An error has occurred, please try again later" data-tx-success="Check your email" class="je-app" ></div>
|
| | | <div style="padding-top:5px;">
|
| | | <table class="table condensed-table">
|
| | | <tbody>
|
| | |
| | | ### WAR: For Your Servlet Container
|
| | | *Gitblit WAR* is what you should download if you already have a servlet container available that you wish to use. Jetty 6/7/8 and Tomcat 6/7 are known to work. Generally, any Servlet 2.5 or Servlet 3.0 container should work.
|
| | |
|
| | | ### Express: For the Cloud
|
| | | *Gitblit Express* is a prepared distribution for [RedHat's OpenShift][rhcloud] cloud service.
|
| | |
|
| | | ### You decide how to use Gitblit
|
| | |
|
| | | Gitblit can be used as a dumb repository viewer with no administrative controls or user accounts.
|
| | | Gitblit can be used as a complete Git stack for cloning, pushing, and repository access control.
|
| | | Gitblit can be used without any other Git tooling (including actual Git) or it can cooperate with your established tools.
|
| | |
|
| | | ### All Transports
|
| | |
|
| | | The SSH, HTTP, & GIT protocols are supported and ready-to-go out of the box.
|
| | |
|
| | | ### Issue tracking with branch-based pull requests
|
| | |
|
| | | Gitblit blends elements of GitHub, BitBucket, and Gerrit to provide a streamlined collaboration workflow based on branches within the primary repository.
|
| | |
|
| | | ### Easy Remote Management
|
| | |
|
| | | Administrators can create and manage all repositories, user accounts, and teams from the *Web UI*.
|
| | | Administrators can create and manage all repositories, user accounts, and teams from the *JSON RPC interface* using the [Gitblit Manager](http://code.google.com/p/gitblit/downloads/detail?name=%MANAGER%) or your own custom tooling.
|
| | | Administrators can create and manage all repositories, user accounts, and teams from the *command-line* using the [Powertools plugin](https://github.com/gitblit/gitblit-powertools-plugin).
|
| | | Administrators can create and manage all repositories, user accounts, and teams from the *command-line* using SSH & the [Powertools plugin](https://github.com/gitblit/gitblit-powertools-plugin).
|
| | |
|
| | | ### Integration with Your Infrastructure
|
| | |
|
| | |
| | |
|
| | | [jgit]: http://eclipse.org/jgit "Eclipse JGit Site"
|
| | | [git]: http://git-scm.com "Official Git Site"
|
| | | [rhcloud]: https://openshift.redhat.com/app "RedHat OpenShift"
|
| | |
| | | |
| | | Additionally, because the patchset is not linked to a user's personal fork it is possible to allow others to collaborate on development. |
| | | |
| | | ## Status |
| | | #### Features |
| | | |
| | | The Tickets feature is highly functional but there are several areas which need further refinements. |
| | | |
| | | #### What is working |
| | | |
| | | - My Tickets page |
| | | - Ticket creation and editing |
| | | - Ticket creation on patchset push |
| | | - Ticket creation on patchset push (proposal) |
| | | - Branch-based pull-requests |
| | | - Comments with Markdown syntax support |
| | | - Rich email notifications |
| | | - Fast-forward patchset updates and patchset rewrites |
| | | - Voting |
| | | - Watching |
| | | - Mentions |
| | | - Partial milestone support |
| | | - Milestones |
| | | - Querying |
| | | - Searching |
| | | - Is Mergeable test on view ticket page load |
| | | - Server-side merge |
| | | - Close-on-push of detected merge |
| | | - Multiple backend choices |
| | | - Server-side merge (testing) |
| | | |
| | | #### TODO |
| | | |
| | | - Implement a My Tickets page (ticket-15) |
| | | - Ticket Lifecycle Hooks (ticket-16) |
| | | - CRUD pages for Milestones (ticket-17) |
| | | - Ticket service migration tool (ticket-19) |
| | | - Collapsible ticket description (e.g. AUI expander) |
| | | - Edit a comment |
| | | - Delete a comment |
| | | - REST API for tooling |
| | | - Client-side Markdown previews (AngularMarkdown?) |
| | |
| | | curl --insecure --user admin:admin "https://localhost:8443/rpc?req=reindex_tickets" |
| | | curl --insecure --user admin:admin "https://localhost:8443/rpc?req=reindex_tickets&name=gitblit.git" |
| | | |
| | | #### Migrating Tickets between Ticket Services |
| | | |
| | | ##### Gitblit GO |
| | | |
| | | Gitblit GO ships with a script that executes the *com.gitblit.MigrateTickets* tool included in the Gitblit jar file. This tool will migrate *all* tickets in *all* repositories **AND** must be run when Gitblit is offline. |
| | | |
| | | migrate-tickets <outputservice> <baseFolder> |
| | | |
| | | For example, this would migrate tickets from the current ticket service configured in `c:\gitblit-data\gitblit.properties` to a Redis ticket service. The Redis service is configured in the same config file so you must be sure to properly setup all appropriate Redis settings. |
| | | |
| | | migrate-tickets com.gitblit.tickets.RedisTicketService c:\gitblit-data |
| | | |
| | | ##### Gitblit WAR |
| | | |
| | | Gitblit WAR does not ship with anything other than the WAR, but you can still migrate tickets offline with a little extra effort. |
| | | |
| | | *Windows* |
| | | |
| | | java -cp "C:/path/to/WEB-INF/lib/*" com.gitblit.MigrateTickets <outputservice> --baseFolder <baseFolder> |
| | | |
| | | *Linux/Unix/Mac OSX* |
| | | |
| | | java -cp /path/to/WEB-INF/lib/* com.gitblit.MigrateTickets <outputservice> --baseFolder <baseFolder> |
| | | |
| | |
| | | |
| | | #### Milestones |
| | | |
| | | Milestones are a way to group tickets together. Currently milestones are specified at the repository level and are stored in the repository git config file. Gitblit's internal architecture has all the methods necessary to maintain milestones, but this functionality is not yet exposed through the web ui. For now you will have to control milestones manually with a text editor. |
| | | Milestones are a way to group tickets together. Milestones are specified for each repository and are stored in the repository git config file. Repository owners may create milestones through the web ui in the *Tickets* page on the *Milestones* tab. |
| | | |
| | | [milestone "v1.5.0"] |
| | | status = Open |
| | |
| | | ...add a single commit... |
| | | git push origin HEAD:refs/for/new |
| | | # read ticket id from server output |
| | | git branch --set-upstream-to=origin/ticket/{id} |
| | | git branch -u origin/ticket/{id} |
| | | |
| | | ### Creating the first Patchset for an Existing Ticket |
| | | |
| | |
| | | cd repo |
| | | git checkout -b ticket/{id} |
| | | ...add one or more commits... |
| | | git push --set-upstream origin ticket/{id} |
| | | git push -u origin ticket/{id} |
| | | |
| | | ### Safely adding commits to a Patchset for an Existing Ticket |
| | | |
| | |
| | | git pull --ff-only |
| | | ...add one or more commits... |
| | | git push |
| | | |
| | | ### Checking-Out a Named Branch for an Existing Ticket with a Patchset |
| | | |
| | | If you prefer to name your local ticket branches rather than using the default integer ids, you can do this with a little more syntax. |
| | | |
| | | git checkout -b my_fix --track origin/ticket/{id} |
| | | |
| | | This will create a local branch named *my_fix* which tracks the upstream ticket branch. |
| | | |
| | | ### Rewriting a Patchset (amend, rebase, squash) |
| | | |
| | |
| | | |
| | | ### Updating your copy of a rewritten Patchset |
| | | |
| | | If a patchset has been rewritten you can no longer simply *pull* to update. Let's assume your checkout **does not** have any unshared commits - i.e. it represents the previous patchset. The simplest way to update your branch to the current patchset is to reset it. |
| | | If a patchset has been rewritten you can no longer simply *pull* to update. Let's assume your checkout **does not** have any unshared commits - i.e. it represents the previous patchset. The simplest way to update your branch to the current patchset is to reset it using the `-B` checkout flag. |
| | | |
| | | git fetch && git checkout ticket/{id} |
| | | git reset --hard origin/ticket/{id} |
| | | git fetch && git checkout -B ticket/{id} |
| | | |
| | | If you **do** have unshared commits then you'll could make a new temporary branch and then cherry-pick your changes onto the rewritten patchset. |
| | | |
| | | git branch oldticket ticket/{id} |
| | | git fetch && git checkout ticket/{id} |
| | | git reset --hard origin/ticket/{id} |
| | | git fetch && git checkout -B ticket/{id} |
| | | git cherry-pick <commitid1> <commitid2> |
| | | git branch -D oldticket |
| | | |
| | | Git is a very flexible tool, there are no doubt several other strategies you could use to resolve this situation. The above solution is just one way. |
| | | |
| | | |
| | | ### Ticket RefSpecs |
| | | |
| | |
| | | |
| | | ### Merging Patchsets |
| | | |
| | | The Gitblit web ui offers a merge button which *should work* but is not fully tested. Gitblit does verify that you can cleanly merge a patchset to the integration branch. |
| | | The Gitblit web ui offers a merge button which will work for clean merges of a patchset to the integration branch. |
| | | |
| | | There are complicated merge scenarios for which it may be best to merge using your Git client. There are several ways to do this, here is a safe merge strategy which pulls into a new branch and then fast-forwards your integration branch, assuming you were happy with the pull (merge). |
| | | |
| | |
| | | password = admin |
| | | cookie = dd94709528bb1c83d08f3088d4043f4742891f4f |
| | | accountType = LOCAL |
| | | emailMeOnMyTicketChanges = true |
| | | role = "#admin" |
| | | role = "#notfederated" |
| | | [user "sampleuser"] |
| | | password = sampleuser |
| | | cookie = 6e07ed42149fc166206319faffdfba2e2ec82e43 |
| | | accountType = LOCAL |
| | | role = "#none" |
| | | [team "admins"] |
| | | role = "#none" |
| | | accountType = LOCAL |
| | |
| | | |
| | | IAuthenticationManager newAuthenticationManager() { |
| | | RuntimeManager runtime = new RuntimeManager(getSettings(), GitBlitSuite.BASEFOLDER).start(); |
| | | users = new UserManager(runtime).start(); |
| | | users = new UserManager(runtime, null).start(); |
| | | AuthenticationManager auth = new AuthenticationManager(runtime, users).start(); |
| | | return auth; |
| | | } |
| | |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings).start(); |
| | | IPluginManager pluginManager = new PluginManager(runtimeManager).start(); |
| | | INotificationManager notificationManager = new NotificationManager(settings).start(); |
| | | IUserManager userManager = new UserManager(runtimeManager).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, userManager).start(); |
| | | IUserManager userManager = new UserManager(runtimeManager, pluginManager).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, pluginManager, userManager).start(); |
| | | |
| | | BranchTicketService service = new BranchTicketService( |
| | | runtimeManager, |
| | |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings).start(); |
| | | IPluginManager pluginManager = new PluginManager(runtimeManager).start(); |
| | | INotificationManager notificationManager = new NotificationManager(settings).start(); |
| | | IUserManager userManager = new UserManager(runtimeManager).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, userManager).start(); |
| | | IUserManager userManager = new UserManager(runtimeManager, pluginManager).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, pluginManager, userManager).start(); |
| | | |
| | | FileTicketService service = new FileTicketService( |
| | | runtimeManager, |
| | |
| | | |
| | | private HtpasswdAuthProvider newHtpasswdAuthentication(IStoredSettings settings) { |
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start(); |
| | | UserManager users = new UserManager(runtime).start(); |
| | | UserManager users = new UserManager(runtime, null).start(); |
| | | HtpasswdAuthProvider htpasswd = new HtpasswdAuthProvider(); |
| | | htpasswd.setup(runtime, users); |
| | | return htpasswd; |
| | | } |
| | | |
| | | |
| | | private AuthenticationManager newAuthenticationManager(IStoredSettings settings) { |
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start(); |
| | | UserManager users = new UserManager(runtime).start(); |
| | | UserManager users = new UserManager(runtime, null).start(); |
| | | HtpasswdAuthProvider htpasswd = new HtpasswdAuthProvider(); |
| | | htpasswd.setup(runtime, users); |
| | | AuthenticationManager auth = new AuthenticationManager(runtime, users); |
| | |
| | | assertEquals("leading", user.username); |
| | | } |
| | | |
| | | |
| | | |
| | | @Test |
| | | public void testAuthenticationManager() |
| | | { |
| | |
| | | private static InMemoryDirectoryServer ds; |
| | | |
| | | private IUserManager userManager; |
| | | |
| | | |
| | | private AuthenticationManager auth; |
| | | |
| | | private MemorySettings settings; |
| | |
| | | |
| | | private LdapAuthProvider newLdapAuthentication(IStoredSettings settings) { |
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start(); |
| | | userManager = new UserManager(runtime).start(); |
| | | userManager = new UserManager(runtime, null).start(); |
| | | LdapAuthProvider ldap = new LdapAuthProvider(); |
| | | ldap.setup(runtime, userManager); |
| | | return ldap; |
| | | } |
| | | |
| | | |
| | | private AuthenticationManager newAuthenticationManager(IStoredSettings settings) { |
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start(); |
| | | AuthenticationManager auth = new AuthenticationManager(runtime, userManager); |
| | |
| | | assertNull(userThreeModel.getTeam("git_admins")); |
| | | assertTrue(userThreeModel.canAdmin); |
| | | } |
| | | |
| | | |
| | | @Test |
| | | public void testBindWithUser() { |
| | | settings.put(Keys.realm.ldap.bindpattern, "CN=${username},OU=US,OU=Users,OU=UserControl,OU=MyOrganization,DC=MyDomain"); |
| | |
| | | |
| | | UserModel userOneModel = auth.authenticate("UserOne", "userOnePassword".toCharArray()); |
| | | assertNotNull(userOneModel); |
| | | |
| | | |
| | | UserModel userOneModelFailedAuth = auth.authenticate("UserOne", "userTwoPassword".toCharArray()); |
| | | assertNull(userOneModelFailedAuth); |
| | | } |
| | |
| | | MemorySettings settings = new MemorySettings();
|
| | | settings.put(Keys.git.repositoriesFolder, GitBlitSuite.REPOSITORIES);
|
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start();
|
| | | UserManager users = new UserManager(runtime).start();
|
| | | RepositoryManager repos = new RepositoryManager(runtime, users);
|
| | | UserManager users = new UserManager(runtime, null).start();
|
| | | RepositoryManager repos = new RepositoryManager(runtime, null, users);
|
| | | return new LuceneService(settings, repos);
|
| | | }
|
| | |
|
| | |
| | | IRuntimeManager runtimeManager = new RuntimeManager(settings).start(); |
| | | IPluginManager pluginManager = new PluginManager(runtimeManager).start(); |
| | | INotificationManager notificationManager = new NotificationManager(settings).start(); |
| | | IUserManager userManager = new UserManager(runtimeManager).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, userManager).start(); |
| | | IUserManager userManager = new UserManager(runtimeManager, pluginManager).start(); |
| | | IRepositoryManager repositoryManager = new RepositoryManager(runtimeManager, pluginManager, userManager).start(); |
| | | |
| | | RedisTicketService service = new RedisTicketService( |
| | | runtimeManager, |
| | |
| | | |
| | | RedmineAuthProvider newRedmineAuthentication(IStoredSettings settings) { |
| | | RuntimeManager runtime = new RuntimeManager(settings, GitBlitSuite.BASEFOLDER).start(); |
| | | UserManager users = new UserManager(runtime).start(); |
| | | UserManager users = new UserManager(runtime, null).start(); |
| | | RedmineAuthProvider redmine = new RedmineAuthProvider(); |
| | | redmine.setup(runtime, users); |
| | | return redmine; |
| | |
| | | RedmineAuthProvider newRedmineAuthentication() { |
| | | return newRedmineAuthentication(getSettings()); |
| | | } |
| | | |
| | | |
| | | AuthenticationManager newAuthenticationManager() { |
| | | RuntimeManager runtime = new RuntimeManager(getSettings(), GitBlitSuite.BASEFOLDER).start(); |
| | | UserManager users = new UserManager(runtime).start(); |
| | | UserManager users = new UserManager(runtime, null).start(); |
| | | RedmineAuthProvider redmine = new RedmineAuthProvider(); |
| | | redmine.setup(runtime, users); |
| | | redmine.setTestingCurrentUserAsJson(JSON); |
| | |
| | | assertNotNull(branches);
|
| | | assertTrue(branches.size() > 0);
|
| | | }
|
| | |
|
| | | @Test
|
| | | public void testFork() throws Exception {
|
| | | // test forking by an administrator
|
| | | // admins are all-powerful and can fork the unforakable :)
|
| | | testFork(account, password, true, true);
|
| | | testFork(account, password, false, true);
|
| | |
|
| | | // test forking by a permitted normal user
|
| | | UserModel forkUser = new UserModel("forkuser");
|
| | | forkUser.password = forkUser.username;
|
| | | forkUser.canFork = true;
|
| | | RpcUtils.deleteUser(forkUser, url, account, password.toCharArray());
|
| | | RpcUtils.createUser(forkUser, url, account, password.toCharArray());
|
| | | testFork(forkUser.username, forkUser.password, true, true);
|
| | | testFork(forkUser.username, forkUser.password, false, false);
|
| | | RpcUtils.deleteUser(forkUser, url, account, password.toCharArray());
|
| | |
|
| | | // test forking by a non-permitted normal user
|
| | | UserModel noForkUser = new UserModel("noforkuser");
|
| | | noForkUser.password = noForkUser.username;
|
| | | noForkUser.canFork = false;
|
| | | RpcUtils.deleteUser(noForkUser, url, account, password.toCharArray());
|
| | | RpcUtils.createUser(noForkUser, url, account, password.toCharArray());
|
| | | testFork(forkUser.username, forkUser.password, true, false);
|
| | | testFork(forkUser.username, forkUser.password, false, false);
|
| | | RpcUtils.deleteUser(noForkUser, url, account, password.toCharArray());
|
| | | }
|
| | |
|
| | | private void testFork(String forkAcct, String forkAcctPassword, boolean allowForks, boolean expectSuccess) throws Exception {
|
| | | // test does not exist
|
| | | RepositoryModel dne = new RepositoryModel();
|
| | | dne.name = "doesNotExist.git";
|
| | | assertFalse(String.format("Successfully forked %s!", dne.name),
|
| | | RpcUtils.forkRepository(dne, url, forkAcct, forkAcctPassword.toCharArray()));
|
| | |
|
| | | // delete any previous fork
|
| | | RepositoryModel fork = findRepository(String.format("~%s/helloworld.git", forkAcct));
|
| | | if (fork != null) {
|
| | | RpcUtils.deleteRepository(fork, url, account, password.toCharArray());
|
| | | }
|
| | |
|
| | | // update the origin to allow forks or not
|
| | | RepositoryModel origin = findRepository("helloworld.git");
|
| | | origin.allowForks = allowForks;
|
| | | RpcUtils.updateRepository(origin.name, origin, url, account, password.toCharArray());
|
| | |
|
| | | // fork the repository
|
| | | if (expectSuccess) {
|
| | | assertTrue(String.format("Failed to fork %s!", origin.name),
|
| | | RpcUtils.forkRepository(origin, url, forkAcct, forkAcctPassword.toCharArray()));
|
| | | } else {
|
| | | assertFalse(String.format("Successfully forked %s!", origin.name),
|
| | | RpcUtils.forkRepository(origin, url, forkAcct, forkAcctPassword.toCharArray()));
|
| | | }
|
| | |
|
| | | // attempt another fork
|
| | | assertFalse(String.format("Successfully forked %s!", origin.name),
|
| | | RpcUtils.forkRepository(origin, url, forkAcct, forkAcctPassword.toCharArray()));
|
| | |
|
| | | // delete the fork repository
|
| | | RpcUtils.deleteRepository(fork, url, account, password.toCharArray());
|
| | | }
|
| | | }
|
| | |
| | | import java.util.HashSet;
|
| | | import java.util.List;
|
| | | import java.util.Set;
|
| | | import java.util.concurrent.atomic.AtomicBoolean;
|
| | |
|
| | | import org.junit.AfterClass;
|
| | | import org.junit.BeforeClass;
|
| | | import org.junit.Test;
|
| | |
|
| | | import com.gitblit.Constants.SearchType;
|
| | |
| | | import com.gitblit.utils.SyndicationUtils;
|
| | |
|
| | | public class SyndicationUtilsTest extends GitblitUnitTest {
|
| | |
|
| | | private static final AtomicBoolean started = new AtomicBoolean(false);
|
| | |
|
| | | @BeforeClass
|
| | | public static void startGitblit() throws Exception {
|
| | | started.set(GitBlitSuite.startGitblit());
|
| | | }
|
| | |
|
| | | @AfterClass
|
| | | public static void stopGitblit() throws Exception {
|
| | | if (started.get()) {
|
| | | GitBlitSuite.stopGitblit();
|
| | | }
|
| | | }
|
| | |
|
| | | @Test
|
| | | public void testSyndication() throws Exception {
|
| | |
| | | }
|
| | |
|
| | | @Test
|
| | | public void testFeedRead() throws Exception {
|
| | | public void testFeedReadCommits() throws Exception {
|
| | | Set<String> links = new HashSet<String>();
|
| | | for (int i = 0; i < 2; i++) {
|
| | | List<FeedEntryModel> feed = SyndicationUtils.readFeed(GitBlitSuite.url, "ticgit.git",
|
| | |
| | | }
|
| | |
|
| | | @Test
|
| | | public void testFeedReadTags() throws Exception {
|
| | | Set<String> links = new HashSet<String>();
|
| | | for (int i = 0; i < 2; i++) {
|
| | | List<FeedEntryModel> feed = SyndicationUtils.readTags(GitBlitSuite.url, "test/gitective.git",
|
| | | 5, i, GitBlitSuite.account, GitBlitSuite.password.toCharArray());
|
| | | assertTrue(feed != null);
|
| | | assertTrue(feed.size() > 0);
|
| | | assertEquals(5, feed.size());
|
| | | for (FeedEntryModel entry : feed) {
|
| | | links.add(entry.link);
|
| | | }
|
| | | }
|
| | | // confirm we have 10 unique tags
|
| | | assertEquals("Feed pagination failed", 10, links.size());
|
| | | }
|
| | |
|
| | | @Test
|
| | | public void testSearchFeedRead() throws Exception {
|
| | | List<FeedEntryModel> feed = SyndicationUtils
|
| | | .readSearchFeed(GitBlitSuite.url, "ticgit.git", null, "test", null, 5, 0,
|
| | |
| | | // query non-existent ticket
|
| | | TicketModel nonExistent = service.getTicket(getRepository(), 0);
|
| | | assertNull(nonExistent);
|
| | | |
| | |
|
| | | // create and insert a ticket
|
| | | Change c1 = newChange("testCreation() " + Long.toHexString(System.currentTimeMillis()));
|
| | | TicketModel ticket = service.createTicket(getRepository(), c1);
|
| | |
| | | assertEquals(1, results.size());
|
| | | assertTrue(results.get(0).title.startsWith("testUpdates"));
|
| | |
|
| | | // check the ids
|
| | | assertEquals("[1, 2]", service.getIds(getRepository()).toString());
|
| | |
|
| | | // delete all tickets
|
| | | for (TicketModel aTicket : allTickets) {
|
| | | assertTrue(service.deleteTicket(getRepository(), aTicket.number, "D"));
|
| | |
| | | } |
| | | |
| | | @Override |
| | | public boolean isServingHTTP() { |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isServingGIT() { |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isServingSSH() { |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isDebugMode() { |
| | | return true; |
| | | } |