- Use standard ServletRequestWrapper instead of custom wrapper (issue 224)\r
\r
additions: \r
- - Support --baseFolder parameter in Federation Client\r
+ - Option to automatically tag branch tips on each push with an incremental revision number\r
+ - Implemented multiple repository owners\r
- Optional periodic LDAP user and team pre-fetching & synchronization\r
- Display name and version in Tomcat Manager\r
- FogBugz post-receive hook script\r
- - Implemented multiple repository owners\r
- Chinese translation\r
+ - Support --baseFolder parameter in Federation Client\r
- Added weblogic.xml to WAR for deployment on WebLogic (issue 199)\r
- Support username substitution in web.otherUrls (issue 213)\r
- Option to force client-side basic authentication instead of form-based authentication if web.authenticateViewPages=true (issue 222)\r
\r
dependencyChanges:\r
- JGit 2.3.1.201302201838-r\r
+ \r
+ settings:\r
+ - { name: 'git.defaultIncrementalPushTagPrefix', defaultValue: 'r' }\r
}\r
\r
#\r
# SINCE 1.1.0\r
git.defaultAuthorizationControl = NAMED\r
\r
+# The default incremental push tag prefix. Tag prefix applied to a repository\r
+# that has automatic push tags enabled and does not specify a custom tag prefix.\r
+#\r
+# If incremental push tags are enabled, the tips of each branch in the push will\r
+# be tagged with an increasing revision integer.\r
+#\r
+# e.g. refs/tags/r2345 or refs/tags/rev_2345 \r
+#\r
+# SINCE 1.3.0\r
+git.defaultIncrementalPushTagPrefix = r\r
+\r
# Enable JGit-based garbage collection. (!!EXPERIMENTAL!!)\r
#\r
# USE AT YOUR OWN RISK!\r
model.addOwners(ArrayUtils.fromString(getConfig(config, "owner", "")));\r
model.useTickets = getConfig(config, "useTickets", false);\r
model.useDocs = getConfig(config, "useDocs", false);\r
- model.useIncrementalRevisionNumbers = getConfig(config, "useIncrementalRevisionNumbers", false);\r
+ model.useIncrementalPushTags = getConfig(config, "useIncrementalPushTags", false);\r
+ model.incrementalPushTagPrefix = getConfig(config, "incrementalPushTagPrefix", null);\r
model.allowForks = getConfig(config, "allowForks", true);\r
model.accessRestriction = AccessRestrictionType.fromName(getConfig(config,\r
"accessRestriction", settings.getString(Keys.git.defaultAccessRestriction, null)));\r
config.setString(Constants.CONFIG_GITBLIT, null, "owner", ArrayUtils.toString(repository.owners));\r
config.setBoolean(Constants.CONFIG_GITBLIT, null, "useTickets", repository.useTickets);\r
config.setBoolean(Constants.CONFIG_GITBLIT, null, "useDocs", repository.useDocs);\r
- config.setBoolean(Constants.CONFIG_GITBLIT, null, "useIncrementalRevisionNumbers", repository.useIncrementalRevisionNumbers);\r
+ config.setBoolean(Constants.CONFIG_GITBLIT, null, "useIncrementalPushTags", repository.useIncrementalPushTags);\r
+ if (StringUtils.isEmpty(repository.incrementalPushTagPrefix) ||\r
+ repository.incrementalPushTagPrefix.equals(settings.getString(Keys.git.defaultIncrementalPushTagPrefix, "r"))) {\r
+ config.unset(Constants.CONFIG_GITBLIT, null, "incrementalPushTagPrefix");\r
+ } else {\r
+ config.setString(Constants.CONFIG_GITBLIT, null, "incrementalPushTagPrefix", repository.incrementalPushTagPrefix);\r
+ }\r
config.setBoolean(Constants.CONFIG_GITBLIT, null, "allowForks", repository.allowForks);\r
config.setString(Constants.CONFIG_GITBLIT, null, "accessRestriction", repository.accessRestriction.name());\r
config.setString(Constants.CONFIG_GITBLIT, null, "authorizationControl", repository.authorizationControl.name());\r
import java.text.MessageFormat;\r
import java.util.Collection;\r
import java.util.Enumeration;\r
-import java.util.Iterator;\r
import java.util.LinkedHashSet;\r
import java.util.List;\r
import java.util.Map;\r
import javax.servlet.ServletContext;\r
import javax.servlet.ServletException;\r
import javax.servlet.http.HttpServletRequest;\r
-import javax.servlet.http.Part;\r
\r
-import org.eclipse.jgit.api.Git;\r
import org.eclipse.jgit.http.server.resolver.DefaultReceivePackFactory;\r
import org.eclipse.jgit.http.server.resolver.DefaultUploadPackFactory;\r
import org.eclipse.jgit.lib.PersonIdent;\r
import org.slf4j.LoggerFactory;\r
\r
import com.gitblit.Constants.AccessRestrictionType;\r
+import com.gitblit.client.Translation;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.models.UserModel;\r
import com.gitblit.utils.ClientLogger;\r
return;\r
}\r
\r
- UserModel user = getUserModel(rp);\r
+ UserModel user = getUserModel(rp); \r
RepositoryModel repository = GitBlit.self().getRepositoryModel(repositoryName);\r
\r
- if (repository.useIncrementalRevisionNumbers) {\r
- List<ReceiveCommand> allCommands = rp.getAllCommands();\r
- String cmds = "";\r
- for (ReceiveCommand receiveCommand : allCommands) {\r
- cmds += receiveCommand.getType() + "_"\r
- + receiveCommand.getResult() + "_"\r
- + receiveCommand.getMessage() + ", ";\r
- if (receiveCommand.getType().equals(\r
- ReceiveCommand.Type.UPDATE)\r
- && receiveCommand.getResult().equals(\r
- ReceiveCommand.Result.OK)) {\r
- // if type=update and update was ok, autotag\r
- String objectId = receiveCommand.getNewId().toString()\r
- .replace("AnyObjectId[", "").replace("]", "");\r
- boolean result = JGitUtils\r
- .createIncrementalRevisionTag(\r
- rp.getRepository(), objectId); \r
+ if (repository.useIncrementalPushTags) {\r
+ // tag each pushed branch tip\r
+ String emailAddress = user.emailAddress == null ? rp.getRefLogIdent().getEmailAddress() : user.emailAddress;\r
+ PersonIdent userIdent = new PersonIdent(user.getDisplayName(), emailAddress);\r
+\r
+ for (ReceiveCommand cmd : commands) {\r
+ if (!cmd.getRefName().startsWith("refs/heads/")) {\r
+ // only tag branch ref changes\r
+ continue;\r
+ }\r
+ \r
+ if (!ReceiveCommand.Type.DELETE.equals(cmd.getType())\r
+ && ReceiveCommand.Result.OK.equals(cmd.getResult())) {\r
+ String objectId = cmd.getNewId().getName();\r
+ String branch = cmd.getRefName().substring("refs/heads/".length());\r
+ // get translation based on the server's locale setting\r
+ String template = Translation.get("gb.incrementalPushTagMessage");\r
+ String msg = MessageFormat.format(template, branch);\r
+ String prefix;\r
+ if (StringUtils.isEmpty(repository.incrementalPushTagPrefix)) {\r
+ prefix = GitBlit.getString(Keys.git.defaultIncrementalPushTagPrefix, "r");\r
+ } else {\r
+ prefix = repository.incrementalPushTagPrefix;\r
+ }\r
+ \r
+ JGitUtils.createIncrementalRevisionTag(\r
+ rp.getRepository(),\r
+ objectId,\r
+ userIdent,\r
+ prefix,\r
+ "0",\r
+ msg);\r
}\r
} \r
}\r
case CREATE:\r
logger.info(MessageFormat.format("{0} CREATED {1} in {2}", user.username, cmd.getRefName(), repository.name));\r
break;\r
+ case UPDATE:\r
+ logger.info(MessageFormat.format("{0} UPDATED {1} in {2} (from {3} to {4})", user.username, cmd.getRefName(), repository.name, cmd.getOldId().name(), cmd.getNewId().name()));\r
+ break;\r
case UPDATE_NONFASTFORWARD:\r
logger.info(MessageFormat.format("{0} UPDATED NON-FAST-FORWARD {1} in {2} (from {3} to {4})", user.username, cmd.getRefName(), repository.name, cmd.getOldId().name(), cmd.getNewId().name()));\r
break;\r
\r
private JCheckBox useDocs;\r
\r
- private JCheckBox useIncrementalRevisionNumbers;\r
+ private JCheckBox useIncrementalPushTags;\r
\r
private JCheckBox showRemoteBranches;\r
\r
anRepository.useTickets);\r
useDocs = new JCheckBox(Translation.get("gb.useDocsDescription"),\r
anRepository.useDocs);\r
- useIncrementalRevisionNumbers = new JCheckBox(Translation.get("gb.useIncrementalRevisionNumbersDescription"),\r
- anRepository.useIncrementalRevisionNumbers);\r
+ useIncrementalPushTags = new JCheckBox(Translation.get("gb.useIncrementalPushTagsDescription"),\r
+ anRepository.useIncrementalPushTags);\r
showRemoteBranches = new JCheckBox(\r
Translation.get("gb.showRemoteBranchesDescription"),\r
anRepository.showRemoteBranches);\r
fieldsPanel\r
.add(newFieldPanel(Translation.get("gb.enableDocs"), useDocs));\r
fieldsPanel\r
- .add(newFieldPanel(Translation.get("gb.enableIncrementalRevisionNumbers"), useIncrementalRevisionNumbers));\r
+ .add(newFieldPanel(Translation.get("gb.enableIncrementalPushTags"), useIncrementalPushTags));\r
fieldsPanel.add(newFieldPanel(Translation.get("gb.showRemoteBranches"),\r
showRemoteBranches));\r
fieldsPanel.add(newFieldPanel(Translation.get("gb.showReadme"),\r
repository.gcThreshold = gcThreshold.getText();\r
repository.useTickets = useTickets.isSelected();\r
repository.useDocs = useDocs.isSelected();\r
- repository.useIncrementalRevisionNumbers = useIncrementalRevisionNumbers.isSelected();\r
+ repository.useIncrementalPushTags = useIncrementalPushTags.isSelected();\r
repository.showRemoteBranches = showRemoteBranches.isSelected();\r
repository.showReadme = showReadme.isSelected();\r
repository.skipSizeCalculation = skipSizeCalculation.isSelected();\r
public boolean showRemoteBranches;\r
public boolean useTickets;\r
public boolean useDocs;\r
- public boolean useIncrementalRevisionNumbers;\r
+ public boolean useIncrementalPushTags;\r
+ public String incrementalPushTagPrefix;\r
public AccessRestrictionType accessRestriction;\r
public AuthorizationControl authorizationControl;\r
public boolean allowAuthenticated;\r
clone.showRemoteBranches = false;\r
clone.allowForks = false;\r
clone.useDocs = useDocs;\r
- clone.useIncrementalRevisionNumbers = useIncrementalRevisionNumbers;\r
clone.useTickets = useTickets;\r
clone.skipSizeCalculation = skipSizeCalculation;\r
clone.skipSummaryMetrics = skipSummaryMetrics;\r
package com.gitblit.utils;\r
\r
import java.io.ByteArrayOutputStream;\r
+import java.text.MessageFormat;\r
import java.util.ArrayList;\r
import java.util.List;\r
\r
lines.add(line);\r
}\r
} catch (Throwable t) {\r
- LOGGER.error("failed to generate blame!", t);\r
+ LOGGER.error(MessageFormat.format("failed to generate blame for {0} {1}!", blobPath, objectId), t);\r
}\r
return lines;\r
}\r
import java.io.File;\r
import java.io.IOException;\r
import java.io.InputStream;\r
+import java.text.DecimalFormat;\r
import java.text.MessageFormat;\r
import java.util.ArrayList;\r
import java.util.Arrays;\r
import org.slf4j.Logger;\r
import org.slf4j.LoggerFactory;\r
\r
-import com.gitblit.GitBlit;\r
-import com.gitblit.Keys;\r
import com.gitblit.models.GitNote;\r
import com.gitblit.models.PathModel;\r
import com.gitblit.models.PathModel.PathChangeModel;\r
*/\r
public class JGitUtils {\r
\r
- private static final String REVISION_TAG_PREFIX = "rev_";\r
static final Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class);\r
\r
/**\r
}\r
return list;\r
}\r
- \r
+\r
/**\r
* this method creates an incremental revision number as a tag according to\r
- * the amount of already existing tags, which start with a defined prefix {@link REVISION_TAG_PREFIX}\r
+ * the amount of already existing tags, which start with a defined prefix.\r
* \r
* @param repository\r
* @param objectId\r
+ * @param tagger\r
+ * @param prefix\r
+ * @param intPattern\r
+ * @param message\r
* @return true if operation was successful, otherwise false\r
*/\r
- public static boolean createIncrementalRevisionTag(Repository repository, String objectId) {\r
+ public static boolean createIncrementalRevisionTag(Repository repository,\r
+ String objectId, PersonIdent tagger, String prefix, String intPattern, String message) {\r
boolean result = false;\r
Iterator<Entry<String, Ref>> iterator = repository.getTags().entrySet().iterator();\r
- long revisionNumber = 1;\r
+ long lastRev = 0;\r
while (iterator.hasNext()) {\r
Entry<String, Ref> entry = iterator.next();\r
- if (entry.getKey().startsWith(REVISION_TAG_PREFIX)) {\r
- revisionNumber++;\r
+ if (entry.getKey().startsWith(prefix)) {\r
+ try {\r
+ long val = Long.parseLong(entry.getKey().substring(prefix.length()));\r
+ if (val > lastRev) {\r
+ lastRev = val;\r
+ }\r
+ } catch (Exception e) {\r
+ // this tag is NOT an incremental revision tag\r
+ }\r
}\r
}\r
- result = createTag(repository,REVISION_TAG_PREFIX+revisionNumber,objectId);\r
+ DecimalFormat df = new DecimalFormat(intPattern);\r
+ result = createTag(repository, objectId, tagger, prefix + df.format((lastRev + 1)), message);\r
return result;\r
}\r
\r
- /**\r
- * creates a tag in a repository referring to the current head\r
- * \r
- * @param repository\r
- * @param tag, the string label\r
- * @return boolean, true if operation was successful, otherwise false\r
- */\r
- public static boolean createTag(Repository repository, String tag) {\r
- return createTag(repository, tag, null);\r
- }\r
- \r
/**\r
* creates a tag in a repository\r
* \r
* @param repository\r
- * @param tag, the string label\r
* @param objectId, the ref the tag points towards\r
+ * @param tagger, the person tagging the object\r
+ * @param tag, the string label\r
+ * @param message, the string message\r
* @return boolean, true if operation was successful, otherwise false\r
*/\r
- public static boolean createTag(Repository repository, String tag,\r
- String objectId) {\r
+ public static boolean createTag(Repository repository, String objectId, PersonIdent tagger, String tag, String message) {\r
try { \r
- PersonIdent author = new PersonIdent("GitblitAutoTagPush",\r
- "gitblit@localhost");\r
-\r
- LOGGER.debug("createTag in repo: "+repository.getDirectory().getAbsolutePath());\r
Git gitClient = Git.open(repository.getDirectory());\r
TagCommand tagCommand = gitClient.tag();\r
- tagCommand.setTagger(author);\r
- tagCommand.setMessage("autotag");\r
+ tagCommand.setTagger(tagger);\r
+ tagCommand.setMessage(message);\r
if (objectId != null) {\r
RevObject revObj = getCommit(repository, objectId);\r
tagCommand.setObjectId(revObj);\r
Ref call = tagCommand.call(); \r
return call != null ? true : false;\r
} catch (Exception e) {\r
- e.printStackTrace();\r
+ error(e, repository, "Failed to create tag {1} in repository {0}", objectId, tag);\r
}\r
return false;\r
}\r
gb.name = name\r
gb.enableTickets = enable tickets\r
gb.enableDocs = enable docs\r
-gb.enableIncrementalRevisionNumbers = enable incremental revision numbers\r
gb.save = save\r
gb.showRemoteBranches = show remote branches\r
gb.editUsers = edit users\r
gb.viewRestricted = authenticated view, clone, & push\r
gb.useTicketsDescription = readonly, distributed Ticgit issues\r
gb.useDocsDescription = enumerates Markdown documentation in repository\r
-gb.useIncrementalRevisionNumbersDescription = automatic tagging of each push with an incremental revision number\r
gb.showRemoteBranchesDescription = show remote branches\r
gb.canAdminDescription = can administer Gitblit server\r
gb.permittedUsers = permitted users\r
gb.sessionEnded = Session has been closed\r
gb.closeBrowser = Please close the browser to properly end the session.\r
gb.doesNotExistInTree = {0} does not exist in tree {1}
+gb.enableIncrementalPushTags = enable incremental push tags\r
+gb.useIncrementalPushTagsDescription = on push, automatically tag each branch tip with an incremental revision number\r
+gb.incrementalPushTagMessage = Auto-tagged [{0}] branch on push
\ No newline at end of file
<tr><th colspan="2"><hr/></th></tr>\r
<tr><th><wicket:message key="gb.enableTickets"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="useTickets" tabindex="7" /> <span class="help-inline"><wicket:message key="gb.useTicketsDescription"></wicket:message></span></label></td></tr>\r
<tr><th><wicket:message key="gb.enableDocs"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="useDocs" tabindex="8" /> <span class="help-inline"><wicket:message key="gb.useDocsDescription"></wicket:message></span></label></td></tr>\r
- <tr><th><wicket:message key="gb.enableIncrementalRevisionNumbers"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="useIncrementalRevisionNumbers" tabindex="8" /> <span class="help-inline"><wicket:message key="gb.useIncrementalRevisionNumbersDescription"></wicket:message></span></label></td></tr>\r
+ <tr><th><wicket:message key="gb.enableIncrementalPushTags"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="useIncrementalPushTags" tabindex="8" /> <span class="help-inline"><wicket:message key="gb.useIncrementalPushTagsDescription"></wicket:message></span></label></td></tr>\r
<tr><th><wicket:message key="gb.showRemoteBranches"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="showRemoteBranches" tabindex="9" /> <span class="help-inline"><wicket:message key="gb.showRemoteBranchesDescription"></wicket:message></span></label></td></tr>\r
<tr><th><wicket:message key="gb.showReadme"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="showReadme" tabindex="10" /> <span class="help-inline"><wicket:message key="gb.showReadmeDescription"></wicket:message></span></label></td></tr>\r
<tr><th><wicket:message key="gb.skipSizeCalculation"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="skipSizeCalculation" tabindex="11" /> <span class="help-inline"><wicket:message key="gb.skipSizeCalculationDescription"></wicket:message></span></label></td></tr>\r
new FederationTypeRenderer()));\r
form.add(new CheckBox("useTickets"));\r
form.add(new CheckBox("useDocs"));\r
- form.add(new CheckBox("useIncrementalRevisionNumbers"));\r
+ form.add(new CheckBox("useIncrementalPushTags"));\r
form.add(new CheckBox("showRemoteBranches"));\r
form.add(new CheckBox("showReadme"));\r
form.add(new CheckBox("skipSizeCalculation"));\r
enableTickets("ticgit.git");\r
enableDocs("ticgit.git");\r
showRemoteBranches("ticgit.git");\r
+ automaticallyTagBranchTips("ticgit.git");\r
showRemoteBranches("test/jgit.git");\r
+ automaticallyTagBranchTips("test/jgit.git"); \r
}\r
}\r
\r
}\r
}\r
\r
+ private static void automaticallyTagBranchTips(String repositoryName) {\r
+ try {\r
+ RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);\r
+ model.useIncrementalPushTags = true;\r
+ GitBlit.self().updateRepositoryModel(model.name, model, false);\r
+ } catch (GitBlitException g) {\r
+ g.printStackTrace();\r
+ }\r
+ }\r
+ \r
public static void close(File repository) {\r
try {\r
File gitDir = FileKey.resolve(repository, FS.detect());\r
w.close();\r
git.add().addFilepattern(file.getName()).call();\r
git.commit().setMessage("test commit").call();\r
- git.push().setPushAll().call();\r
+ git.push().setPushAll().setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password)).call();\r
GitBlitSuite.close(git);\r
}\r
\r
git.commit().setMessage("test commit").call();\r
\r
try {\r
- git.push().setPushAll().call();\r
+ git.push().setPushAll().setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password)).call();\r
assertTrue(false);\r
} catch (Exception e) {\r
assertTrue(e.getCause().getMessage().contains("access forbidden"));\r
model.isFrozen = false;\r
GitBlit.self().updateRepositoryModel(model.name, model, false);\r
\r
- git.push().setPushAll().call();\r
+ git.push().setPushAll().setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password)).call();\r
GitBlitSuite.close(git);\r
}\r
\r
git.add().addFilepattern(file.getName()).call();\r
git.commit().setMessage("test commit followed by push to non-bare repository").call();\r
try {\r
- git.push().setPushAll().call();\r
+ git.push().setPushAll().setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password)).call();\r
assertTrue(false);\r
} catch (Exception e) {\r
assertTrue(e.getCause().getMessage().contains("git-receive-pack not permitted"));\r