diff options
author | James Moger <james.moger@gitblit.com> | 2014-06-03 08:38:55 -0600 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2014-06-03 08:38:55 -0600 |
commit | 42972d830611fa4b1aa2c2c49c824a15e1987597 (patch) | |
tree | 8f3edf5322c852ab9b85f62fbd5b7ff7b15c4399 | |
parent | e1bcda8c6245035c96bf44ee09d61fa5a52bcafc (diff) | |
parent | b79824366fe4814e6912fa38f6da7939b6f27124 (diff) | |
download | gitblit-42972d830611fa4b1aa2c2c49c824a15e1987597.tar.gz gitblit-42972d830611fa4b1aa2c2c49c824a15e1987597.zip |
Merged #76 "Simplify repository creation with a new page"
38 files changed, 1621 insertions, 287 deletions
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..01eaa2c8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/main/distrib/data/gitignore"] + path = src/main/distrib/data/gitignore + url = https://github.com/github/gitignore.git diff --git a/README.markdown b/README.markdown index 348afae4..76c15fce 100644 --- a/README.markdown +++ b/README.markdown @@ -4,7 +4,7 @@ Gitblit Gitblit is an open source, pure Java Git solution for managing, viewing, and serving [Git](http://git-scm.com) repositories.
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
-------
@@ -12,6 +12,11 @@ License Gitblit is distributed under the terms of the [Apache Software Foundation license, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
The text of the license is included in the file LICENSE in the root of the project.
+Contributing
+------------
+
+GitHub pull requests 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).
+
Java Runtime Requirement
------------------------------------
@@ -25,6 +30,10 @@ Issues, binaries, & sources @ [Google Code](http://code.google.com/p/gitblit) 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.
@@ -39,4 +48,4 @@ Building Gitblit 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.
\ No newline at end of file +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.
@@ -919,6 +919,12 @@ <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>
diff --git a/releases.moxie b/releases.moxie index 4332238d..7635e064 100644 --- a/releases.moxie +++ b/releases.moxie @@ -27,6 +27,7 @@ r24: { - 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) - Overhaul the EmptyRepositoryPage (ticket-73) + - Overhauled the edit repository page (ticket-76) - Process bugtraq links in the ticket description and comments (ticket-78) additions: - Add My Tickets page (issue-215, ticket-15) @@ -36,6 +37,7 @@ r24: { - 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 setting to control default thread pool size for miscellaneous background tasks (ticket-92) @@ -55,6 +57,7 @@ r24: { - { name: 'web.allowDeletingNonEmptyRepositories', defaultValue: 'true' } - { name: 'mail.starttls', defaultValue: 'false' } - { name: 'execution.defaultThreadPoolSize', defaultValue: '1' } + - { name: 'git.gitignoreFolder', defaultValue: '${baseFolder}/gitignore' } } # diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties index 6f55a3eb..d5623cd5 100644 --- a/src/main/distrib/data/gitblit.properties +++ b/src/main/distrib/data/gitblit.properties @@ -271,6 +271,11 @@ git.defaultIncrementalPushTagPrefix = r # 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!
diff --git a/src/main/distrib/data/gitignore b/src/main/distrib/data/gitignore new file mode 160000 +Subproject 097db81c08b138dea7cb031eb18eeb16afe44bd diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index 95eb944a..3e307537 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -122,6 +122,14 @@ public class Constants { 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();
if (v == null) {
diff --git a/src/main/java/com/gitblit/servlet/GitblitContext.java b/src/main/java/com/gitblit/servlet/GitblitContext.java index 110e553c..50f22d5a 100644 --- a/src/main/java/com/gitblit/servlet/GitblitContext.java +++ b/src/main/java/com/gitblit/servlet/GitblitContext.java @@ -372,6 +372,22 @@ public class GitblitContext extends DaggerContext { } } + // 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); diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java index 7291d039..f63ff3d9 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java @@ -57,6 +57,7 @@ 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; @@ -71,6 +72,7 @@ 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; @@ -92,6 +94,8 @@ 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>(); private final IStoredSettings settings; @@ -207,6 +211,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { 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"); @@ -262,6 +268,10 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { return homePageClass; } + public Class<? extends WebPage> getNewRepositoryPage() { + return newRepositoryPageClass; + } + /* (non-Javadoc) * @see com.gitblit.wicket.Webapp#isCacheablePage(java.lang.String) */ diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 12430ade..d6fd57e9 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -133,7 +133,7 @@ gb.sendProposal = propose 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 @@ -223,8 +223,8 @@ gb.queryResults = results {0} - {1} ({2} hits) 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! @@ -685,4 +685,41 @@ 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.
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html index b7a1976f..1e683b4f 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html @@ -9,14 +9,17 @@ <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 -->
@@ -24,99 +27,167 @@ <!-- 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">
+
+ <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>
+
+ <!-- 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.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>
+ <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>
- </div>
- <!-- federation -->
- <div class="tab-pane" id="federation">
+ <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><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="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>
- </div>
-</div>
-</div>
-</div>
+
+ <!-- misc -->
+ <div class="tab-pane" id="misc">
-<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 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>
</form>
</body>
+
</wicket:extend>
</html>
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index 412c0ecc..f891595c 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -29,7 +29,6 @@ import java.util.Set; 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;
@@ -40,7 +39,6 @@ import org.apache.wicket.markup.html.form.ChoiceRenderer; 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;
@@ -48,6 +46,7 @@ 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;
@@ -69,14 +68,23 @@ import com.gitblit.utils.StringUtils; 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.BulletListPanel;
+import com.gitblit.wicket.panels.CheckboxOption;
+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;
RepositoryModel repositoryModel;
@@ -196,7 +204,7 @@ public class EditRepositoryPage extends RootSubPage { }
}
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>();
@@ -263,60 +271,9 @@ public class EditRepositoryPage extends RootSubPage { @Override
protected void onSubmit() {
try {
- // confirm a repository name was entered
- if (repositoryModel.name == null && StringUtils.isEmpty(repositoryModel.name)) {
- error(getString("gb.pleaseSetRepositoryName"));
- 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"));
+ if (!namePanel.updateModel(repositoryModel)) {
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
if (repositoryModel.accessRestriction == null) {
@@ -426,33 +383,15 @@ public class EditRepositoryPage extends RootSubPage { }
} catch (GitBlitException e) {
error(e.getMessage());
+ namePanel.resetModel(repositoryModel);
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)) {
@@ -465,58 +404,79 @@ public class EditRepositoryPage extends RootSubPage { }
}
}
- 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 CheckboxOption("acceptNewPatchsets",
+ getString("gb.acceptNewPatchsets"),
+ getString("gb.acceptNewPatchsetsDescription"),
+ new PropertyModel<Boolean>(repositoryModel, "acceptNewPatchsets")));
+
+ form.add(new CheckboxOption("acceptNewTickets",
+ getString("gb.acceptNewTickets"),
+ getString("gb.acceptNewTicketsDescription"),
+ new PropertyModel<Boolean>(repositoryModel, "acceptNewPatchsets")));
+
+ form.add(new CheckboxOption("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 CheckboxOption("isFrozen",
+ getString("gb.isFrozen"),
+ getString("gb.isFrozenDescription"),
+ new PropertyModel<Boolean>(repositoryModel, "isFrozen")));
+
+ form.add(new CheckboxOption("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 CheckboxOption("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)));
@@ -528,17 +488,125 @@ public class EditRepositoryPage extends RootSubPage { 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 CheckboxOption("showRemoteBranches",
+ getString("gb.showRemoteBranches"),
+ getString("gb.showRemoteBranchesDescription"),
+ new PropertyModel<Boolean>(repositoryModel, "showRemoteBranches")));
+
+ form.add(new CheckboxOption("skipSizeCalculation",
+ getString("gb.skipSizeCalculation"),
+ getString("gb.skipSizeCalculationDescription"),
+ new PropertyModel<Boolean>(repositoryModel, "skipSizeCalculation")));
+
+ form.add(new CheckboxOption("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);
@@ -546,15 +614,18 @@ public class EditRepositoryPage extends RootSubPage { 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);
@@ -565,41 +636,19 @@ public class EditRepositoryPage extends RootSubPage { repositoryModel.authorizationControl = AuthorizationControl.NAMED;
}
- target.addComponent(authorizationControl);
target.addComponent(verifyCommitter);
target.addComponent(usersPalette);
target.addComponent(teamsPalette);
}
- });
-
- authorizationControl.add(new AjaxFormChoiceComponentUpdatingBehavior() {
-
- 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);
- }
- });
+ accessPolicyPanel = new AccessPolicyPanel("accessPolicyPanel", repositoryModel, callback);
+ form.add(accessPolicyPanel);
- 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;
@@ -632,7 +681,15 @@ public class EditRepositoryPage extends RootSubPage { if (canDelete) {
if (app().repositories().deleteRepositoryModel(latestModel)) {
info(MessageFormat.format(getString("gb.repositoryDeleted"), latestModel));
- setResponsePage(RepositoriesPage.class);
+ 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));
}
@@ -697,26 +754,6 @@ public class EditRepositoryPage extends RootSubPage { }
}
- 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> {
@@ -739,27 +776,6 @@ public class EditRepositoryPage extends RootSubPage { }
}
- 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);
- }
- }
-
private class GCPeriodRenderer implements IChoiceRenderer<Integer> {
private static final long serialVersionUID = 1L;
diff --git a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.html index ebd513ad..31226ff5 100644 --- a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.html @@ -10,7 +10,7 @@ <div class="markdown">
<div class="row">
<div class="span10 offset1">
- <h2><center>Empty Repository</center></h2>
+ <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>
diff --git a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_es.html b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_es.html index 0f168bff..af75b4ee 100644 --- a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_es.html +++ b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_es.html @@ -12,7 +12,7 @@ <div class="markdown">
<div class="row">
<div class="span10 offset1">
- <h2><center>Repositorio Vacío</center></h2>
+ <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>
diff --git a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_ko.html b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_ko.html index bd1f4f5f..7fbcee13 100644 --- a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_ko.html +++ b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_ko.html @@ -10,7 +10,7 @@ <div class="markdown"> <div class="row"> <div class="span10 offset1"> - <h2><center>비어있는 저장소</center></h2> + <h3><center>비어있는 저장소</center></h3> <div class="alert alert-info"> <span wicket:id="repository" style="font-weight: bold;">[repository]</span> 저장소는 비어 있어서 Gitblit 에서 볼 수 없습니다. <p></p> diff --git a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_nl.html b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_nl.html index dd58ed46..84373d20 100644 --- a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_nl.html +++ b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_nl.html @@ -10,7 +10,7 @@ <div class="markdown">
<div class="row">
<div class="span10 offset1">
- <h2><center>Lege Repository</center></h2>
+ <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>
diff --git a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_pl.html b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_pl.html index dd0f4a5d..b50bdac3 100644 --- a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_pl.html +++ b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_pl.html @@ -12,7 +12,7 @@ <div class="markdown"> <div class="row"> <div class="span10 offset1"> - <h2><center>Puste repozytorium</center></h2> + <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> diff --git a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_pt_BR.html b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_pt_BR.html index 0182d87e..fc201210 100644 --- a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_pt_BR.html +++ b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_pt_BR.html @@ -10,7 +10,7 @@ <div class="markdown">
<div class="row">
<div class="span10 offset1">
- <h2><center>Repositório Vazio</center></h2>
+ <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>
diff --git a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_zh_CN.html b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_zh_CN.html index 151abc42..1acf4f82 100644 --- a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_zh_CN.html +++ b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage_zh_CN.html @@ -10,7 +10,7 @@ <div class="markdown"> <div class="row"> <div class="span10 offset1"> - <h2><center>空版本库</center></h2> + <h3><center>空版本库</center></h3> <div class="alert alert-info"> <span wicket:id="repository" style="font-weight: bold;">[repository]</span> 版本库目前为空。 Gitblit 无法查看。 diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html new file mode 100644 index 00000000..115b8c10 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html @@ -0,0 +1,41 @@ +<!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>
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java new file mode 100644 index 00000000..bc2c68cc --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -0,0 +1,373 @@ +/*
+ * 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.CheckboxOption;
+import com.gitblit.wicket.panels.ConditionalChoiceOption;
+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());
+ namePanel.resetModel(repositoryModel);
+ 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 CheckboxOption("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 ConditionalChoiceOption<String>("addGitIgnore",
+ getString("gb.initWithGitignore"),
+ getString("gb.initWithGitignoreDescription"),
+ addGitignoreModel,
+ gitignoreModel,
+ gitignores));
+
+ // TODO consider gitflow at creation (ticket-55)
+ addGitflowModel = Model.of(false);
+ form.add(new CheckboxOption("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;
+ }
+}
diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java index a2f3a497..b1c3639d 100644 --- a/src/main/java/com/gitblit/wicket/pages/RootPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java @@ -607,7 +607,7 @@ public abstract class RootPage extends BasePage { List<MenuItem> standardItems = new ArrayList<MenuItem>(); standardItems.add(new MenuDivider()); if (user.canAdmin() || user.canCreate()) { - standardItems.add(new PageLinkMenuItem("gb.newRepository", EditRepositoryPage.class)); + standardItems.add(new PageLinkMenuItem("gb.newRepository", app().getNewRepositoryPage())); } standardItems.add(new PageLinkMenuItem("gb.myProfile", UserPage.class, WicketUtils.newUsernameParameter(user.username))); diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 6cb791eb..29b49b33 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -30,8 +30,8 @@ import org.eclipse.jgit.lib.PersonIdent; 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.NavLink.DropDownPageMenuNavLink;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
@@ -95,7 +95,7 @@ public class UserPage extends RootPage { 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));
+ add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));
} else {
add(new Label("newRepository").setVisible(false));
}
diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html new file mode 100644 index 00000000..a2d76b7e --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html @@ -0,0 +1,28 @@ +<!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;"><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>
+
+ <hr />
+
+ <div wicket:id="allowForks"></div>
+
+</wicket:panel>
+</body>
+</html>
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java new file mode 100644 index 00000000..4f234263 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java @@ -0,0 +1,192 @@ +/*
+ * 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.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(true);
+ add(new CheckboxOption("allowForks",
+ getString("gb.allowForks"),
+ getString("gb.allowForksDescription"),
+ allowForks).setEnabled(app().settings().getBoolean(Keys.web.allowForking, true)));
+
+ 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;
+ }
+ }
+}
diff --git a/src/main/java/com/gitblit/wicket/panels/CheckboxOption.html b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.html new file mode 100644 index 00000000..6684fe92 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.html @@ -0,0 +1,17 @@ +<!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;" 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>
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java new file mode 100644 index 00000000..08eeaa24 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/CheckboxOption.java @@ -0,0 +1,54 @@ +/*
+ * 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 CheckboxOption extends BasePanel {
+
+ private static final long serialVersionUID = 1L;
+
+ public CheckboxOption(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 CheckboxOption(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 CheckboxOption setIsHtmlDescription(boolean val) {
+ ((Label) get("description")).setEscapeModelStrings(!val);
+ return this;
+ }
+}
diff --git a/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html new file mode 100644 index 00000000..8c34c819 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html @@ -0,0 +1,19 @@ +<!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>
+ <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>
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/ChoiceOption.java b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.java new file mode 100644 index 00000000..9c25b70a --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.java @@ -0,0 +1,52 @@ +/*
+ * 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));
+ }
+}
diff --git a/src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.html b/src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.html new file mode 100644 index 00000000..fb360d12 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.html @@ -0,0 +1,19 @@ +<!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;" 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>
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.java b/src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.java new file mode 100644 index 00000000..07aaee84 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/ConditionalChoiceOption.java @@ -0,0 +1,78 @@ +/*
+ * 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 ConditionalChoiceOption<T> extends BasePanel {
+
+ private static final long serialVersionUID = 1L;
+
+ final CheckBox checkbox;
+ final DropDownChoice<T> choice;
+
+ public ConditionalChoiceOption(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);
+ }
+ }
+ });
+ }
+}
diff --git a/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java b/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java index 45b0bab1..4433b043 100644 --- a/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java +++ b/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java @@ -33,7 +33,6 @@ import com.gitblit.utils.StringUtils; 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,
@@ -98,7 +97,7 @@ public class FilterableRepositoryList extends BasePanel { }
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));
}
diff --git a/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html b/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html index eb82245c..a48797ec 100644 --- a/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html +++ b/src/main/java/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html @@ -16,7 +16,7 @@ </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>
diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java index dd208e23..8573e1a6 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java @@ -51,7 +51,6 @@ 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.ProjectPage;
import com.gitblit.wicket.pages.RepositoriesPage;
import com.gitblit.wicket.pages.SummaryPage;
@@ -87,12 +86,12 @@ public class RepositoriesPanel extends BasePanel { 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
diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html new file mode 100644 index 00000000..6fb6e45c --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html @@ -0,0 +1,30 @@ +<!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>
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java new file mode 100644 index 00000000..358ff59b --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java @@ -0,0 +1,176 @@ +/*
+ * 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 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 DropDownChoice<String> projectChoice;
+
+ 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 defaultProject = null;
+ Set<String> projectNames = 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) {
+ projectNames.add("/");
+ } else {
+ projectNames.add(project.name + "/");
+ }
+ }
+ }
+
+ // add the user's personal project namespace
+ if (user.canAdmin() || user.canCreate()) {
+ projectNames.add(user.getPersonalPath() + "/");
+ }
+
+ if (!StringUtils.isEmpty(repository.name)) {
+ // editing a repository name
+ // set the defaultProject to the current repository project
+ defaultProject = repository.projectPath;
+ if (StringUtils.isEmpty(defaultProject)) {
+ defaultProject = "/";
+ } else {
+ defaultProject += "/";
+ }
+
+ projectNames.add(defaultProject);
+ }
+
+ // if default project is not already set, set preference based on the user permissions
+ if (defaultProject == null) {
+ if (user.canAdmin()) {
+ defaultProject = "/";
+ } else if (user.canCreate()) {
+ defaultProject = user.getPersonalPath() + "/";
+ }
+ }
+
+ // update the model which is reflectively mapped to the Wicket fields by name
+ repository.projectPath = defaultProject;
+ if (repository.projectPath.length() > 1 && !StringUtils.isEmpty(repository.name)) {
+ repository.name = repository.name.substring(repository.projectPath.length());
+ }
+ projectChoice = new DropDownChoice<String>("projectPath", new ArrayList<String>(projectNames));
+ nameField = new TextField<String>("name");
+
+ // only enable project selection if we actually have multiple choices
+ add(projectChoice.setEnabled(projectNames.size() > 1));
+ add(nameField);
+ add(new TextField<String>("description"));
+ }
+
+ public void setEditable(boolean editable) {
+ // only enable project selection if we actually have multiple choices
+ projectChoice.setEnabled(projectChoice.getChoices().size() > 1 && editable);
+ nameField.setEnabled(editable);
+ }
+
+ public boolean updateModel(RepositoryModel repositoryModel) {
+ // confirm a project was selected
+ if (StringUtils.isEmpty(repositoryModel.projectPath)) {
+ error(getString("gb.pleaseSelectProject"));
+ return false;
+ }
+
+ // confirm a repository name was entered
+ if (StringUtils.isEmpty(repositoryModel.name)) {
+ error(getString("gb.pleaseSetRepositoryName"));
+ return false;
+ }
+
+ String project = repositoryModel.projectPath;
+
+ fullName = (project + repositoryModel.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;
+ repositoryModel.projectPath = null;
+
+ return true;
+ }
+
+ public void resetModel(RepositoryModel repositoryModel) {
+ // restore project and name fields on error condition
+ repositoryModel.projectPath = StringUtils.getFirstPathElement(fullName) + "/";
+ if (repositoryModel.projectPath.length() > 1) {
+ repositoryModel.name = fullName.substring(repositoryModel.projectPath.length());
+ }
+ }
+
+ @Override
+ protected boolean getStatelessHint() {
+ return false;
+ }
+}
diff --git a/src/main/java/com/gitblit/wicket/panels/TextOption.html b/src/main/java/com/gitblit/wicket/panels/TextOption.html new file mode 100644 index 00000000..ff2da78e --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/TextOption.html @@ -0,0 +1,20 @@ +<!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>
+ <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="span2" type="text" wicket:id="text" /></p>
+ </label>
+
+ </div>
+</wicket:panel>
+</body>
+</html>
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/TextOption.java b/src/main/java/com/gitblit/wicket/panels/TextOption.java new file mode 100644 index 00000000..22370f3c --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/TextOption.java @@ -0,0 +1,53 @@ +/*
+ * 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);
+ }
+}
|