summaryrefslogtreecommitdiffstats
path: root/src/main/distrib/data/groovy
diff options
context:
space:
mode:
authorJames Moger <james.moger@gitblit.com>2013-03-27 12:46:05 -0400
committerJames Moger <james.moger@gitblit.com>2013-03-27 17:22:08 -0400
commitf6b200be4c8b90c26886c6cdd5809abac8c4ac15 (patch)
treea948dbcf6f24bf884ad95a8d6830b4ec4e1706cf /src/main/distrib/data/groovy
parentb79ade104858ce6714a7329b7629b331564a2ea5 (diff)
downloadgitblit-f6b200be4c8b90c26886c6cdd5809abac8c4ac15.tar.gz
gitblit-f6b200be4c8b90c26886c6cdd5809abac8c4ac15.zip
Reorganized to Apache Standard Directory Layout & integrated Moxie
This is a massive commit which reorganizes the entire project structure (although it is still monolithic), removes the Build classes, and switches to Moxie, a smarter Ant build tookit based on the original Gitblit Build classes. The Ant build script will likely require additional fine-tuning, but this is big step forward.
Diffstat (limited to 'src/main/distrib/data/groovy')
-rw-r--r--src/main/distrib/data/groovy/.gitignore1
-rw-r--r--src/main/distrib/data/groovy/blockpush.groovy94
-rw-r--r--src/main/distrib/data/groovy/jenkins.groovy76
-rw-r--r--src/main/distrib/data/groovy/localclone.groovy106
-rw-r--r--src/main/distrib/data/groovy/protect-refs.groovy113
-rw-r--r--src/main/distrib/data/groovy/sendmail-html.groovy516
-rw-r--r--src/main/distrib/data/groovy/sendmail.groovy176
-rw-r--r--src/main/distrib/data/groovy/thebuggenie.groovy88
8 files changed, 1170 insertions, 0 deletions
diff --git a/src/main/distrib/data/groovy/.gitignore b/src/main/distrib/data/groovy/.gitignore
new file mode 100644
index 00000000..e58dc47f
--- /dev/null
+++ b/src/main/distrib/data/groovy/.gitignore
@@ -0,0 +1 @@
+/grape
diff --git a/src/main/distrib/data/groovy/blockpush.groovy b/src/main/distrib/data/groovy/blockpush.groovy
new file mode 100644
index 00000000..caef3306
--- /dev/null
+++ b/src/main/distrib/data/groovy/blockpush.groovy
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.text.MessageFormat;
+
+import com.gitblit.GitBlit
+import com.gitblit.models.RepositoryModel
+import com.gitblit.models.UserModel
+import org.eclipse.jgit.transport.ReceiveCommand
+import org.eclipse.jgit.transport.ReceiveCommand.Result
+import org.slf4j.Logger
+import com.gitblit.utils.ClientLogger
+
+/**
+ * Sample Gitblit Pre-Receive Hook: blockpush
+ *
+ * This script could and perhaps should be further developed to provide
+ * a full repository-branch permissions system similar to gitolite or gitosis.
+ *
+ * The Pre-Receive hook is executed after an incoming push has been parsed,
+ * validated, and objects have been written but BEFORE the refs are updated.
+ * This is the appropriate point to block a push for some reason.
+ *
+ * This script is only executed when pushing to *Gitblit*, not to other Git
+ * tooling you may be using.
+ *
+ * If this script is specified in *groovy.preReceiveScripts* of gitblit.properties
+ * or web.xml then it will be executed by any repository when it receives a
+ * push. If you choose to share your script then you may have to consider
+ * tailoring control-flow based on repository access restrictions.
+ *
+ * Scripts may also be specified per-repository in the repository settings page.
+ * Shared scripts will be excluded from this list of available scripts.
+ *
+ * This script is dynamically reloaded and it is executed within it's own
+ * exception handler so it will not crash another script nor crash Gitblit.
+ *
+ * If you want this hook script to fail and abort all subsequent scripts in the
+ * chain, "return false" at the appropriate failure points.
+ *
+ * Bound Variables:
+ * gitblit Gitblit Server com.gitblit.GitBlit
+ * repository Gitblit Repository com.gitblit.models.RepositoryModel
+ * receivePack JGit Receive Pack org.eclipse.jgit.transport.ReceivePack
+ * user Gitblit User com.gitblit.models.UserModel
+ * commands JGit commands Collection<org.eclipse.jgit.transport.ReceiveCommand>
+ * url Base url for Gitblit String
+ * logger Logs messages to Gitblit org.slf4j.Logger
+ * clientLogger Logs messages to Git client com.gitblit.utils.ClientLogger
+ *
+ * Accessing Gitblit Custom Fields:
+ * def myCustomField = repository.customFields.myCustomField
+ *
+ */
+
+// Indicate we have started the script
+logger.info("blockpush hook triggered by ${user.username} for ${repository.name}: checking ${commands.size} commands")
+
+/*
+ * Example rejection of pushes to the master branch of example.git
+ */
+def blocked = false
+switch (repository.name) {
+ case 'ex@mple.git':
+ for (ReceiveCommand command : commands) {
+ def updatedRef = command.refName
+ if (updatedRef.equals('refs/heads/master')) {
+ // to reject a command set it's result to anything other than Result.NOT_ATTEMPTED
+ command.setResult(Result.REJECTED_OTHER_REASON, "You are not permitted to write to ${repository.name}:${updatedRef}")
+ blocked = true
+ }
+ }
+ break
+
+ default:
+ break
+}
+
+if (blocked) {
+ // return false to break the push hook chain
+ return false
+} \ No newline at end of file
diff --git a/src/main/distrib/data/groovy/jenkins.groovy b/src/main/distrib/data/groovy/jenkins.groovy
new file mode 100644
index 00000000..d76a3d66
--- /dev/null
+++ b/src/main/distrib/data/groovy/jenkins.groovy
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import com.gitblit.GitBlit
+import com.gitblit.Keys
+import com.gitblit.models.RepositoryModel
+import com.gitblit.models.UserModel
+import com.gitblit.utils.JGitUtils
+import org.eclipse.jgit.lib.Repository
+import org.eclipse.jgit.revwalk.RevCommit
+import org.eclipse.jgit.transport.ReceiveCommand
+import org.eclipse.jgit.transport.ReceiveCommand.Result
+import org.slf4j.Logger
+
+/**
+ * Sample Gitblit Post-Receive Hook: jenkins
+ *
+ * The Post-Receive hook is executed AFTER the pushed commits have been applied
+ * to the Git repository. This is the appropriate point to trigger an
+ * integration build or to send a notification.
+ *
+ * This script is only executed when pushing to *Gitblit*, not to other Git
+ * tooling you may be using.
+ *
+ * If this script is specified in *groovy.postReceiveScripts* of gitblit.properties
+ * or web.xml then it will be executed by any repository when it receives a
+ * push. If you choose to share your script then you may have to consider
+ * tailoring control-flow based on repository access restrictions.
+ *
+ * Scripts may also be specified per-repository in the repository settings page.
+ * Shared scripts will be excluded from this list of available scripts.
+ *
+ * This script is dynamically reloaded and it is executed within it's own
+ * exception handler so it will not crash another script nor crash Gitblit.
+ *
+ * Bound Variables:
+ * gitblit Gitblit Server com.gitblit.GitBlit
+ * repository Gitblit Repository com.gitblit.models.RepositoryModel
+ * receivePack JGit Receive Pack org.eclipse.jgit.transport.ReceivePack
+ * user Gitblit User com.gitblit.models.UserModel
+ * commands JGit commands Collection<org.eclipse.jgit.transport.ReceiveCommand>
+ * url Base url for Gitblit String
+ * logger Logs messages to Gitblit org.slf4j.Logger
+ * clientLogger Logs messages to Git client com.gitblit.utils.ClientLogger
+ *
+ * Accessing Gitblit Custom Fields:
+ * def myCustomField = repository.customFields.myCustomField
+ *
+ */
+// Indicate we have started the script
+logger.info("jenkins hook triggered by ${user.username} for ${repository.name}")
+
+// This script requires Jenkins Git plugin 1.1.14 or later
+// http://kohsuke.org/2011/12/01/polling-must-die-triggering-jenkins-builds-from-a-git-hook/
+
+// define your jenkins url here or set groovy.jenkinsServer in
+// gitblit.properties or web.xml
+def jenkinsUrl = gitblit.getString('groovy.jenkinsServer', 'http://yourserver/jenkins')
+
+// define the trigger url
+def triggerUrl = jenkinsUrl + "/git/notifyCommit?url=$url/git/$repository.name"
+
+// trigger the build
+new URL(triggerUrl).getContent()
diff --git a/src/main/distrib/data/groovy/localclone.groovy b/src/main/distrib/data/groovy/localclone.groovy
new file mode 100644
index 00000000..49b7f8b3
--- /dev/null
+++ b/src/main/distrib/data/groovy/localclone.groovy
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import com.gitblit.GitBlit
+import com.gitblit.Keys
+import com.gitblit.models.RepositoryModel
+import com.gitblit.models.TeamModel
+import com.gitblit.models.UserModel
+import com.gitblit.utils.JGitUtils
+import com.gitblit.utils.StringUtils
+import java.text.SimpleDateFormat
+import org.eclipse.jgit.api.CloneCommand
+import org.eclipse.jgit.api.Git
+import org.eclipse.jgit.lib.Repository
+import org.eclipse.jgit.lib.Config
+import org.eclipse.jgit.revwalk.RevCommit
+import org.eclipse.jgit.transport.ReceiveCommand
+import org.eclipse.jgit.transport.ReceiveCommand.Result
+import org.eclipse.jgit.util.FileUtils
+import org.slf4j.Logger
+
+/**
+ * Sample Gitblit Post-Receive Hook: localclone
+ *
+ * The Post-Receive hook is executed AFTER the pushed commits have been applied
+ * to the Git repository. This is the appropriate point to trigger an
+ * integration build or to send a notification.
+ *
+ * This script is only executed when pushing to *Gitblit*, not to other Git
+ * tooling you may be using.
+ *
+ * If this script is specified in *groovy.postReceiveScripts* of gitblit.properties
+ * or web.xml then it will be executed by any repository when it receives a
+ * push. If you choose to share your script then you may have to consider
+ * tailoring control-flow based on repository access restrictions.
+ *
+ * Scripts may also be specified per-repository in the repository settings page.
+ * Shared scripts will be excluded from this list of available scripts.
+ *
+ * This script is dynamically reloaded and it is executed within it's own
+ * exception handler so it will not crash another script nor crash Gitblit.
+ *
+ * If you want this hook script to fail and abort all subsequent scripts in the
+ * chain, "return false" at the appropriate failure points.
+ *
+ * Bound Variables:
+ * gitblit Gitblit Server com.gitblit.GitBlit
+ * repository Gitblit Repository com.gitblit.models.RepositoryModel
+ * receivePack JGit Receive Pack org.eclipse.jgit.transport.ReceivePack
+ * user Gitblit User com.gitblit.models.UserModel
+ * commands JGit commands Collection<org.eclipse.jgit.transport.ReceiveCommand>
+ * url Base url for Gitblit String
+ * logger Logs messages to Gitblit org.slf4j.Logger
+ * clientLogger Logs messages to Git client com.gitblit.utils.ClientLogger
+ *
+ * Accessing Gitblit Custom Fields:
+ * def myCustomField = repository.customFields.myCustomField
+ *
+ */
+
+// Indicate we have started the script
+logger.info("localclone hook triggered by ${user.username} for ${repository.name}")
+
+def rootFolder = 'c:/test'
+def bare = false
+def cloneAllBranches = true
+def cloneBranch = 'refs/heads/master'
+def includeSubmodules = true
+
+def repoName = repository.name
+def destinationFolder = new File(rootFolder, StringUtils.stripDotGit(repoName))
+def srcUrl = 'file://' + new File(GitBlit.getRepositoriesFolder(), repoName).absolutePath
+
+// delete any previous clone
+if (destinationFolder.exists()) {
+ FileUtils.delete(destinationFolder, FileUtils.RECURSIVE)
+}
+
+// clone the repository
+logger.info("cloning ${srcUrl} to ${destinationFolder}")
+CloneCommand cmd = Git.cloneRepository();
+cmd.setBare(bare)
+if (cloneAllBranches)
+ cmd.setCloneAllBranches(true)
+else
+ cmd.setBranch(cloneBranch)
+cmd.setCloneSubmodules(includeSubmodules)
+cmd.setURI(srcUrl)
+cmd.setDirectory(destinationFolder)
+Git git = cmd.call();
+git.repository.close()
+
+// report clone operation success back to pushing Git client
+clientLogger.info("${repoName} cloned to ${destinationFolder}") \ No newline at end of file
diff --git a/src/main/distrib/data/groovy/protect-refs.groovy b/src/main/distrib/data/groovy/protect-refs.groovy
new file mode 100644
index 00000000..b1b611f4
--- /dev/null
+++ b/src/main/distrib/data/groovy/protect-refs.groovy
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2012 Philip L. McMahon.
+ *
+ * Derived from blockpush.groovy, copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import com.gitblit.GitBlit
+import com.gitblit.models.RepositoryModel
+import com.gitblit.models.UserModel
+
+import org.eclipse.jgit.transport.ReceiveCommand
+import org.eclipse.jgit.transport.ReceiveCommand.Result
+import org.slf4j.Logger
+
+/**
+ * Sample Gitblit Pre-Receive Hook: protect-refs
+ *
+ * This script provides basic authorization of receive command types for a list
+ * of known ref patterns. Command types and unmatched ref patterns will be
+ * ignored, meaning this script has an "allow by default" policy.
+ *
+ * This script works best when a repository requires authentication on push, but
+ * can be used to enforce fast-forward commits or prohibit ref deletion by
+ * setting the *authorizedTeams* variable to an empty list and adding a ".+"
+ * entry to the *protectedRefs* list.
+ *
+ * The Pre-Receive hook is executed after an incoming push has been parsed,
+ * validated, and objects have been written but BEFORE the refs are updated.
+ * This is the appropriate point to block a push for some reason.
+ *
+ * This script is only executed when pushing to *Gitblit*, not to other Git
+ * tooling you may be using.
+ *
+ * If this script is specified in *groovy.preReceiveScripts* of gitblit.properties
+ * or web.xml then it will be executed by any repository when it receives a
+ * push. If you choose to share your script then you may have to consider
+ * tailoring control-flow based on repository access restrictions.
+ *
+ * Scripts may also be specified per-repository in the repository settings page.
+ * Shared scripts will be excluded from this list of available scripts.
+ *
+ * This script is dynamically reloaded and it is executed within it's own
+ * exception handler so it will not crash another script nor crash Gitblit.
+ *
+ * This script may reject one or more commands, but will never return false.
+ * Subsequent scripts, if any, will always be invoked.
+ *
+ * Bound Variables:
+ * gitblit Gitblit Server com.gitblit.GitBlit
+ * repository Gitblit Repository com.gitblit.models.RepositoryModel
+ * receivePack JGit Receive Pack org.eclipse.jgit.transport.ReceivePack
+ * user Gitblit User com.gitblit.models.UserModel
+ * commands JGit commands Collection<org.eclipse.jgit.transport.ReceiveCommand>
+ * url Base url for Gitblit String
+ * logger Logs messages to Gitblit org.slf4j.Logger
+ * clientLogger Logs messages to Git client com.gitblit.utils.ClientLogger
+ *
+ * Accessing Gitblit Custom Fields:
+ * def myCustomField = repository.customFields.myCustomField
+ *
+ */
+
+// map of protected command types to returned results type
+// commands not included will skip authz check
+def protectedCmds = [
+ UPDATE_NONFASTFORWARD: Result.REJECTED_NONFASTFORWARD,
+ DELETE: Result.REJECTED_NODELETE
+]
+
+// list of regex patterns for protected refs
+def protectedRefs = [
+ "refs/heads/master",
+ "refs/tags/.+"
+]
+
+// teams which are authorized to perform protected commands on protected refs
+def authorizedTeams = [ "admins" ]
+
+for (ReceiveCommand command : commands) {
+ def updateType = command.type
+ def updatedRef = command.refName
+
+ // find first regex which matches updated ref, if any
+ def refPattern = protectedRefs.find { updatedRef.matches ~it }
+
+ // find rejection result for update type, if any
+ def result = protectedCmds[updateType.name()]
+
+ // command requires authz if ref is protected and has a mapped rejection result
+ if (refPattern && result) {
+
+ // verify user is a member of any authorized team
+ def team = authorizedTeams.find { user.isTeamMember it }
+ if (team) {
+ // don't adjust command result
+ logger.info "${user.username} authorized for ${updateType} of protected ref ${repository.name}:${updatedRef} (${command.oldId.name} -> ${command.newId.name})"
+ } else {
+ // mark command result as rejected
+ command.setResult(result, "${user.username} cannot ${updateType} protected ref ${repository.name}:${updatedRef} matching pattern ${refPattern}")
+ }
+ }
+}
diff --git a/src/main/distrib/data/groovy/sendmail-html.groovy b/src/main/distrib/data/groovy/sendmail-html.groovy
new file mode 100644
index 00000000..16920735
--- /dev/null
+++ b/src/main/distrib/data/groovy/sendmail-html.groovy
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2012 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import com.gitblit.GitBlit
+import com.gitblit.Keys
+import com.gitblit.models.RepositoryModel
+import com.gitblit.models.TeamModel
+import com.gitblit.models.UserModel
+import com.gitblit.utils.JGitUtils
+import java.text.SimpleDateFormat
+
+import org.eclipse.jgit.api.Status;
+import org.eclipse.jgit.api.errors.JGitInternalException;
+import org.eclipse.jgit.diff.DiffEntry;
+import org.eclipse.jgit.diff.DiffFormatter;
+import org.eclipse.jgit.diff.RawTextComparator;
+import org.eclipse.jgit.diff.DiffEntry.ChangeType;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.IndexDiff;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository
+import org.eclipse.jgit.lib.Config
+import org.eclipse.jgit.patch.FileHeader;
+import org.eclipse.jgit.revwalk.RevCommit
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.ReceiveCommand
+import org.eclipse.jgit.transport.ReceiveCommand.Result
+import org.eclipse.jgit.treewalk.FileTreeIterator;
+import org.eclipse.jgit.treewalk.EmptyTreeIterator;
+import org.eclipse.jgit.treewalk.CanonicalTreeParser;
+import org.eclipse.jgit.util.io.DisabledOutputStream;
+import org.slf4j.Logger
+import groovy.xml.MarkupBuilder
+
+import java.io.IOException;
+import java.security.MessageDigest
+
+
+/**
+ * Sample Gitblit Post-Receive Hook: sendmail-html
+ *
+ * The Post-Receive hook is executed AFTER the pushed commits have been applied
+ * to the Git repository. This is the appropriate point to trigger an
+ * integration build or to send a notification.
+ *
+ * This script is only executed when pushing to *Gitblit*, not to other Git
+ * tooling you may be using.
+ *
+ * If this script is specified in *groovy.postReceiveScripts* of gitblit.properties
+ * or web.xml then it will be executed by any repository when it receives a
+ * push. If you choose to share your script then you may have to consider
+ * tailoring control-flow based on repository access restrictions.
+ *
+ * Scripts may also be specified per-repository in the repository settings page.
+ * Shared scripts will be excluded from this list of available scripts.
+ *
+ * This script is dynamically reloaded and it is executed within it's own
+ * exception handler so it will not crash another script nor crash Gitblit.
+ *
+ * If you want this hook script to fail and abort all subsequent scripts in the
+ * chain, "return false" at the appropriate failure points.
+ *
+ * Bound Variables:
+ * gitblit Gitblit Server com.gitblit.GitBlit
+ * repository Gitblit Repository com.gitblit.models.RepositoryModel
+ * user Gitblit User com.gitblit.models.UserModel
+ * commands JGit commands Collection<org.eclipse.jgit.transport.ReceiveCommand>
+ * url Base url for Gitblit java.lang.String
+ * logger Logs messages to Gitblit org.slf4j.Logger
+ * clientLogger Logs messages to Git client com.gitblit.utils.ClientLogger
+ *
+ * Accessing Gitblit Custom Fields:
+ * def myCustomField = repository.customFields.myCustomField
+ *
+ */
+
+com.gitblit.models.UserModel userModel = user
+
+// Indicate we have started the script
+logger.info("sendmail-html hook triggered by ${user.username} for ${repository.name}")
+
+/*
+ * Primitive email notification.
+ * This requires the mail settings to be properly configured in Gitblit.
+ */
+
+Repository r = gitblit.getRepository(repository.name)
+
+// reuse existing repository config settings, if available
+Config config = r.getConfig()
+def mailinglist = config.getString('hooks', null, 'mailinglist')
+def emailprefix = config.getString('hooks', null, 'emailprefix')
+
+// set default values
+def toAddresses = []
+if (emailprefix == null) {
+ emailprefix = '[Gitblit]'
+}
+
+if (mailinglist != null) {
+ def addrs = mailinglist.split(/(,|\s)/)
+ toAddresses.addAll(addrs)
+}
+
+// add all mailing lists defined in gitblit.properties or web.xml
+toAddresses.addAll(GitBlit.getStrings(Keys.mail.mailingLists))
+
+// add all team mailing lists
+def teams = gitblit.getRepositoryTeams(repository)
+for (team in teams) {
+ TeamModel model = gitblit.getTeamModel(team)
+ if (model.mailingLists) {
+ toAddresses.addAll(model.mailingLists)
+ }
+}
+
+// add all mailing lists for the repository
+toAddresses.addAll(repository.mailingLists)
+
+// define the summary and commit urls
+def repo = repository.name
+def summaryUrl = url + "/summary?r=$repo"
+def baseCommitUrl = url + "/commit?r=$repo&h="
+def baseBlobDiffUrl = url + "/blobdiff/?r=$repo&h="
+def baseCommitDiffUrl = url + "/commitdiff/?r=$repo&h="
+def forwardSlashChar = gitblit.getString(Keys.web.forwardSlashCharacter, '/')
+
+if (gitblit.getBoolean(Keys.web.mountParameters, true)) {
+ repo = repo.replace('/', forwardSlashChar).replace('/', '%2F')
+ summaryUrl = url + "/summary/$repo"
+ baseCommitUrl = url + "/commit/$repo/"
+ baseBlobDiffUrl = url + "/blobdiff/$repo/"
+ baseCommitDiffUrl = url + "/commitdiff/$repo/"
+}
+
+class HtmlMailWriter {
+ Repository repository
+ def url
+ def baseCommitUrl
+ def baseCommitDiffUrl
+ def baseBlobDiffUrl
+ def mountParameters
+ def forwardSlashChar
+ def includeGravatar
+ def shortCommitIdLength
+ def commitCount = 0
+ def commands
+ def writer = new StringWriter();
+ def builder = new MarkupBuilder(writer)
+
+ def writeStyle() {
+ builder.style(type:"text/css", '''
+ .table td {
+ vertical-align: middle;
+ }
+ tr.noborder td {
+ border: none;
+ padding-top: 0px;
+ }
+ .gravatar-column {
+ width: 5%;
+ }
+ .author-column {
+ width: 20%;
+ }
+ .commit-column {
+ width: 5%;
+ }
+ .status-column {
+ width: 10%;
+ }
+ .table-disable-hover.table tbody tr:hover td,
+ .table-disable-hover.table tbody tr:hover th {
+ background-color: inherit;
+ }
+ .table-disable-hover.table-striped tbody tr:nth-child(odd):hover td,
+ .table-disable-hover.table-striped tbody tr:nth-child(odd):hover th {
+ background-color: #f9f9f9;
+ }
+ ''')
+ }
+
+ def writeBranchTitle(type, name, action, number) {
+ builder.div('class' : 'pageTitle') {
+ builder.span('class':'project') {
+ mkp.yield "$type "
+ span('class': 'repository', name )
+ if (number > 0) {
+ mkp.yield " $action ($number commits)"
+ } else {
+ mkp.yield " $action"
+ }
+ }
+ }
+ }
+
+ def writeBranchDeletedTitle(type, name) {
+ builder.div('class' : 'pageTitle', 'style':'color:red') {
+ builder.span('class':'project') {
+ mkp.yield "$type "
+ span('class': 'repository', name )
+ mkp.yield " deleted"
+ }
+ }
+ }
+
+ def commitUrl(RevCommit commit) {
+ "${baseCommitUrl}$commit.id.name"
+ }
+
+ def commitDiffUrl(RevCommit commit) {
+ "${baseCommitDiffUrl}$commit.id.name"
+ }
+
+ def encoded(String path) {
+ path.replace('/', forwardSlashChar).replace('/', '%2F')
+ }
+
+ def blobDiffUrl(objectId, path) {
+ if (mountParameters) {
+ // REST style
+ "${baseBlobDiffUrl}${objectId.name()}/${encoded(path)}"
+ } else {
+ "${baseBlobDiffUrl}${objectId.name()}&f=${path}"
+ }
+
+ }
+
+ def writeCommitTable(commits, includeChangedPaths=true) {
+ // Write commits table
+ builder.table('class':"table table-disable-hover") {
+ thead {
+ tr {
+ th(colspan: includeGravatar ? 2 : 1, "Author")
+ th( "Commit" )
+ th( "Message" )
+ }
+ }
+ tbody() {
+
+ // Write all the commits
+ for (commit in commits) {
+ writeCommit(commit)
+
+ if (includeChangedPaths) {
+ // Write detail on that particular commit
+ tr('class' : 'noborder') {
+ td (colspan: includeGravatar ? 3 : 2)
+ td (colspan:2) { writeStatusTable(commit) }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ def writeCommit(commit) {
+ def abbreviated = repository.newObjectReader().abbreviate(commit.id, shortCommitIdLength).name()
+ def author = commit.authorIdent.name
+ def email = commit.authorIdent.emailAddress
+ def message = commit.shortMessage
+ builder.tr {
+ if (includeGravatar) {
+ td('class':"gravatar-column") {
+ img(src:gravatarUrl(email), 'class':"gravatar")
+ }
+ }
+ td('class':"author-column", author)
+ td('class':"commit-column") {
+ a(href:commitUrl(commit)) {
+ span('class':"label label-info", abbreviated )
+ }
+ }
+ td {
+ mkp.yield message
+ a('class':'link', href:commitDiffUrl(commit), " [commitdiff]" )
+ }
+ }
+ }
+
+ def writeStatusLabel(style, tooltip) {
+ builder.span('class' : style, 'title' : tooltip )
+ }
+
+ def writeAddStatusLine(ObjectId id, FileHeader header) {
+ builder.td('class':'changeType') {
+ writeStatusLabel("addition", "addition")
+ }
+ builder.td {
+ a(href:blobDiffUrl(id, header.newPath), header.newPath)
+ }
+ }
+
+ def writeCopyStatusLine(ObjectId id, FileHeader header) {
+ builder.td('class':'changeType') {
+ writeStatusLabel("rename", "rename")
+ }
+ builder.td() {
+ a(href:blobDiffUrl(id, header.newPath), header.oldPath + " copied to " + header.newPath)
+ }
+ }
+
+ def writeDeleteStatusLine(ObjectId id, FileHeader header) {
+ builder.td('class':'changeType') {
+ writeStatusLabel("deletion", "deletion")
+ }
+ builder.td() {
+ a(href:blobDiffUrl(id, header.oldPath), header.oldPath)
+ }
+ }
+
+ def writeModifyStatusLine(ObjectId id, FileHeader header) {
+ builder.td('class':'changeType') {
+ writeStatusLabel("modification", "modification")
+ }
+ builder.td() {
+ a(href:blobDiffUrl(id, header.oldPath), header.oldPath)
+ }
+ }
+
+ def writeRenameStatusLine(ObjectId id, FileHeader header) {
+ builder.td('class':'changeType') {
+ writeStatusLabel("rename", "rename")
+ }
+ builder.td() {
+ mkp.yield header.oldPath
+ mkp.yieldUnescaped "<b> -&rt; </b>"
+ a(href:blobDiffUrl(id, header.newPath), header.newPath)
+ }
+ }
+
+ def writeStatusLine(ObjectId id, FileHeader header) {
+ builder.tr {
+ switch (header.changeType) {
+ case ChangeType.ADD:
+ writeAddStatusLine(id, header)
+ break;
+ case ChangeType.COPY:
+ writeCopyStatusLine(id, header)
+ break;
+ case ChangeType.DELETE:
+ writeDeleteStatusLine(id, header)
+ break;
+ case ChangeType.MODIFY:
+ writeModifyStatusLine(id, header)
+ break;
+ case ChangeType.RENAME:
+ writeRenameStatusLine(id, header)
+ break;
+ }
+ }
+ }
+
+ def writeStatusTable(RevCommit commit) {
+ DiffFormatter formatter = new DiffFormatter(DisabledOutputStream.INSTANCE)
+ formatter.setRepository(repository)
+ formatter.setDetectRenames(true)
+ formatter.setDiffComparator(RawTextComparator.DEFAULT);
+
+ def diffs
+ RevWalk rw = new RevWalk(repository)
+ if (commit.parentCount > 0) {
+ RevCommit parent = rw.parseCommit(commit.parents[0].id)
+ diffs = formatter.scan(parent.tree, commit.tree)
+ } else {
+ diffs = formatter.scan(new EmptyTreeIterator(),
+ new CanonicalTreeParser(null, rw.objectReader, commit.tree))
+ }
+ rw.dispose()
+ // Write status table
+ builder.table('class':"plain") {
+ tbody() {
+ for (DiffEntry entry in diffs) {
+ FileHeader header = formatter.toFileHeader(entry)
+ writeStatusLine(commit.id, header)
+ }
+ }
+ }
+ }
+
+
+ def md5(text) {
+
+ def digest = MessageDigest.getInstance("MD5")
+
+ //Quick MD5 of text
+ def hash = new BigInteger(1, digest.digest(text.getBytes()))
+ .toString(16)
+ .padLeft(32, "0")
+ hash.toString()
+ }
+
+ def gravatarUrl(email) {
+ def cleaned = email.trim().toLowerCase()
+ "http://www.gravatar.com/avatar/${md5(cleaned)}?s=30"
+ }
+
+ def writeNavbar() {
+ builder.div('class':"navbar navbar-fixed-top") {
+ div('class':"navbar-inner") {
+ div('class':"container") {
+ a('class':"brand", href:"${url}", title:"GitBlit") {
+ img(src:"${url}/gitblt_25_white.png",
+ width:"79",
+ height:"25",
+ 'class':"logo")
+ }
+ }
+ }
+ }
+ }
+
+ def write() {
+ builder.html {
+ head {
+ link(rel:"stylesheet", href:"${url}/bootstrap/css/bootstrap.css")
+ link(rel:"stylesheet", href:"${url}/gitblit.css")
+ link(rel:"stylesheet", href:"${url}/bootstrap/css/bootstrap-responsive.css")
+ writeStyle()
+ }
+ body {
+
+ writeNavbar()
+
+ div('class':"container") {
+
+ for (command in commands) {
+ def ref = command.refName
+ def refType = 'Branch'
+ if (ref.startsWith('refs/heads/')) {
+ ref = command.refName.substring('refs/heads/'.length())
+ } else if (ref.startsWith('refs/tags/')) {
+ ref = command.refName.substring('refs/tags/'.length())
+ refType = 'Tag'
+ }
+
+ switch (command.type) {
+ case ReceiveCommand.Type.CREATE:
+ def commits = JGitUtils.getRevLog(repository, command.oldId.name, command.newId.name).reverse()
+ commitCount += commits.size()
+ if (refType == 'Branch') {
+ // new branch
+ writeBranchTitle(refType, ref, "created", commits.size())
+ writeCommitTable(commits, true)
+ } else {
+ // new tag
+ writeBranchTitle(refType, ref, "created", 0)
+ writeCommitTable(commits, false)
+ }
+ break
+ case ReceiveCommand.Type.UPDATE:
+ def commits = JGitUtils.getRevLog(repository, command.oldId.name, command.newId.name).reverse()
+ commitCount += commits.size()
+ // fast-forward branch commits table
+ // Write header
+ writeBranchTitle(refType, ref, "updated", commits.size())
+ writeCommitTable(commits)
+ break
+ case ReceiveCommand.Type.UPDATE_NONFASTFORWARD:
+ def commits = JGitUtils.getRevLog(repository, command.oldId.name, command.newId.name).reverse()
+ commitCount += commits.size()
+ // non-fast-forward branch commits table
+ // Write header
+ writeBranchTitle(refType, ref, "updated [NON fast-forward]", commits.size())
+ writeCommitTable(commits)
+ break
+ case ReceiveCommand.Type.DELETE:
+ // deleted branch/tag
+ writeBranchDeletedTitle(refType, ref)
+ break
+ default:
+ break
+ }
+ }
+ }
+ }
+ }
+ writer.toString()
+ }
+
+}
+
+def mailWriter = new HtmlMailWriter()
+mailWriter.repository = r
+mailWriter.baseCommitUrl = baseCommitUrl
+mailWriter.baseBlobDiffUrl = baseBlobDiffUrl
+mailWriter.baseCommitDiffUrl = baseCommitDiffUrl
+mailWriter.forwardSlashChar = forwardSlashChar
+mailWriter.commands = commands
+mailWriter.url = url
+mailWriter.mountParameters = GitBlit.getBoolean(Keys.web.mountParameters, true)
+mailWriter.includeGravatar = GitBlit.getBoolean(Keys.web.allowGravatar, true)
+mailWriter.shortCommitIdLength = GitBlit.getInteger(Keys.web.shortCommitIdLength, 8)
+
+def content = mailWriter.write()
+
+// close the repository reference
+r.close()
+
+// tell Gitblit to send the message (Gitblit filters duplicate addresses)
+def repositoryName = repository.name.substring(0, repository.name.length() - 4)
+gitblit.sendHtmlMail("${emailprefix} ${userModel.displayName} pushed ${mailWriter.commitCount} commits => $repositoryName",
+ content,
+ toAddresses)
diff --git a/src/main/distrib/data/groovy/sendmail.groovy b/src/main/distrib/data/groovy/sendmail.groovy
new file mode 100644
index 00000000..c832bc64
--- /dev/null
+++ b/src/main/distrib/data/groovy/sendmail.groovy
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import com.gitblit.GitBlit
+import com.gitblit.Keys
+import com.gitblit.models.RepositoryModel
+import com.gitblit.models.TeamModel
+import com.gitblit.models.UserModel
+import com.gitblit.utils.JGitUtils
+import java.text.SimpleDateFormat
+import org.eclipse.jgit.lib.Repository
+import org.eclipse.jgit.lib.Config
+import org.eclipse.jgit.revwalk.RevCommit
+import org.eclipse.jgit.transport.ReceiveCommand
+import org.eclipse.jgit.transport.ReceiveCommand.Result
+import org.slf4j.Logger
+
+/**
+ * Sample Gitblit Post-Receive Hook: sendmail
+ *
+ * The Post-Receive hook is executed AFTER the pushed commits have been applied
+ * to the Git repository. This is the appropriate point to trigger an
+ * integration build or to send a notification.
+ *
+ * This script is only executed when pushing to *Gitblit*, not to other Git
+ * tooling you may be using.
+ *
+ * If this script is specified in *groovy.postReceiveScripts* of gitblit.properties
+ * or web.xml then it will be executed by any repository when it receives a
+ * push. If you choose to share your script then you may have to consider
+ * tailoring control-flow based on repository access restrictions.
+ *
+ * Scripts may also be specified per-repository in the repository settings page.
+ * Shared scripts will be excluded from this list of available scripts.
+ *
+ * This script is dynamically reloaded and it is executed within it's own
+ * exception handler so it will not crash another script nor crash Gitblit.
+ *
+ * If you want this hook script to fail and abort all subsequent scripts in the
+ * chain, "return false" at the appropriate failure points.
+ *
+ * Bound Variables:
+ * gitblit Gitblit Server com.gitblit.GitBlit
+ * repository Gitblit Repository com.gitblit.models.RepositoryModel
+ * receivePack JGit Receive Pack org.eclipse.jgit.transport.ReceivePack
+ * user Gitblit User com.gitblit.models.UserModel
+ * commands JGit commands Collection<org.eclipse.jgit.transport.ReceiveCommand>
+ * url Base url for Gitblit String
+ * logger Logs messages to Gitblit org.slf4j.Logger
+ * clientLogger Logs messages to Git client com.gitblit.utils.ClientLogger
+ *
+ * Accessing Gitblit Custom Fields:
+ * def myCustomField = repository.customFields.myCustomField
+ *
+ */
+
+// Indicate we have started the script
+logger.info("sendmail hook triggered by ${user.username} for ${repository.name}")
+
+/*
+ * Primitive email notification.
+ * This requires the mail settings to be properly configured in Gitblit.
+ */
+
+Repository r = gitblit.getRepository(repository.name)
+
+// reuse existing repository config settings, if available
+Config config = r.getConfig()
+def mailinglist = config.getString('hooks', null, 'mailinglist')
+def emailprefix = config.getString('hooks', null, 'emailprefix')
+
+// set default values
+def toAddresses = []
+if (emailprefix == null)
+emailprefix = '[Gitblit]'
+
+if (mailinglist != null) {
+ def addrs = mailinglist.split(/(,|\s)/)
+ toAddresses.addAll(addrs)
+}
+
+// add all mailing lists defined in gitblit.properties or web.xml
+toAddresses.addAll(gitblit.getStrings(Keys.mail.mailingLists))
+
+// add all team mailing lists
+def teams = gitblit.getRepositoryTeams(repository)
+for (team in teams) {
+ TeamModel model = gitblit.getTeamModel(team)
+ if (model.mailingLists) {
+ toAddresses.addAll(model.mailingLists)
+ }
+}
+
+// add all mailing lists for the repository
+toAddresses.addAll(repository.mailingLists)
+
+// define the summary and commit urls
+def repo = repository.name
+def summaryUrl
+def commitUrl
+if (gitblit.getBoolean(Keys.web.mountParameters, true)) {
+ repo = repo.replace('/', gitblit.getString(Keys.web.forwardSlashCharacter, '/')).replace('/', '%2F')
+ summaryUrl = url + "/summary/$repo"
+ commitUrl = url + "/commit/$repo/"
+} else {
+ summaryUrl = url + "/summary?r=$repo"
+ commitUrl = url + "/commit?r=$repo&h="
+}
+
+// construct a simple text summary of the changes contained in the push
+def branchBreak = '>---------------------------------------------------------------\n'
+def commitBreak = '\n\n ----\n'
+def commitCount = 0
+def changes = ''
+SimpleDateFormat df = new SimpleDateFormat(gitblit.getString(Keys.web.datetimestampLongFormat, 'EEEE, MMMM d, yyyy h:mm a z'))
+def table = { "\n ${JGitUtils.getDisplayName(it.authorIdent)}\n ${df.format(JGitUtils.getCommitDate(it))}\n\n $it.shortMessage\n\n $commitUrl$it.id.name" }
+for (command in commands) {
+ def ref = command.refName
+ def refType = 'branch'
+ if (ref.startsWith('refs/heads/')) {
+ ref = command.refName.substring('refs/heads/'.length())
+ } else if (ref.startsWith('refs/tags/')) {
+ ref = command.refName.substring('refs/tags/'.length())
+ refType = 'tag'
+ }
+
+ switch (command.type) {
+ case ReceiveCommand.Type.CREATE:
+ def commits = JGitUtils.getRevLog(r, command.oldId.name, command.newId.name).reverse()
+ commitCount += commits.size()
+ // new branch
+ changes += "\n$branchBreak new $refType $ref created ($commits.size commits)\n$branchBreak"
+ changes += commits.collect(table).join(commitBreak)
+ changes += '\n'
+ break
+ case ReceiveCommand.Type.UPDATE:
+ def commits = JGitUtils.getRevLog(r, command.oldId.name, command.newId.name).reverse()
+ commitCount += commits.size()
+ // fast-forward branch commits table
+ changes += "\n$branchBreak $ref $refType updated ($commits.size commits)\n$branchBreak"
+ changes += commits.collect(table).join(commitBreak)
+ changes += '\n'
+ break
+ case ReceiveCommand.Type.UPDATE_NONFASTFORWARD:
+ def commits = JGitUtils.getRevLog(r, command.oldId.name, command.newId.name).reverse()
+ commitCount += commits.size()
+ // non-fast-forward branch commits table
+ changes += "\n$branchBreak $ref $refType updated [NON fast-forward] ($commits.size commits)\n$branchBreak"
+ changes += commits.collect(table).join(commitBreak)
+ changes += '\n'
+ break
+ case ReceiveCommand.Type.DELETE:
+ // deleted branch/tag
+ changes += "\n$branchBreak $ref $refType deleted\n$branchBreak"
+ break
+ default:
+ break
+ }
+}
+// close the repository reference
+r.close()
+
+// tell Gitblit to send the message (Gitblit filters duplicate addresses)
+gitblit.sendMail("$emailprefix $user.username pushed $commitCount commits => $repository.name", "$summaryUrl\n$changes", toAddresses) \ No newline at end of file
diff --git a/src/main/distrib/data/groovy/thebuggenie.groovy b/src/main/distrib/data/groovy/thebuggenie.groovy
new file mode 100644
index 00000000..b4385a26
--- /dev/null
+++ b/src/main/distrib/data/groovy/thebuggenie.groovy
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2011 Wolfgang Gassler gassler.org
+ *
+ * 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.
+ */
+
+import com.gitblit.GitBlit
+import com.gitblit.Keys
+import com.gitblit.models.RepositoryModel
+import com.gitblit.models.TeamModel
+import com.gitblit.models.UserModel
+import com.gitblit.utils.JGitUtils
+import java.text.SimpleDateFormat
+import org.eclipse.jgit.lib.Repository
+import org.eclipse.jgit.lib.Config
+import org.eclipse.jgit.revwalk.RevCommit
+import org.eclipse.jgit.transport.ReceiveCommand
+import org.eclipse.jgit.transport.ReceiveCommand.Result
+import org.slf4j.Logger
+import org.eclipse.jgit.lib.IndexDiff
+import org.eclipse.jgit.lib.Constants
+import com.gitblit.utils.DiffUtils
+
+/**
+ * Gitblit Post-Receive Hook: thebuggenie
+ * www.thebuggenie.com
+ *
+ * Submit the commit information to thebuggenie bug tracker by calling thebuggenie client tool
+ *
+ * Config of the Script:
+ *
+ * Setup a custom gitblit field in the proprties file of gitblit by adding the following line
+ * groovy.customFields = "thebuggenieProjectId=TheBugGennie project id (used for thebuggenie hoocks)"
+ * This field allows to specify the project id of thebuggenie project in the edit section of gitblit
+ *
+ * Furthermore you need to set the path to thebuggenie client tool by adding the following property to
+ * the gitblit properties file
+ * thebuggenie.tbg_cli = /var/www/thebuggenie_root/tbg_cli
+ */
+
+// Indicate we have started the script
+logger.info("thebuggenie hook triggered by ${user.username} for ${repository.name}")
+
+//fetch the repository data
+Repository r = gitblit.getRepository(repository.name)
+
+//get project id which is defined in the git repo metadata
+def tbgProjectId = repository.customFields.thebuggenieProjectId
+//get path to the thebuggenie client tool which is defined in the gitblit proprties files
+def tbgCliPath = gitblit.getString('thebuggenie.tbg_cli', '/var/www/thebuggenie/tbg_cli')
+def tbgCliDirPath = new File(tbgCliPath).getParent()
+
+for(command in commands) {
+ //fetch all pushed commits
+ def commits = JGitUtils.getRevLog(r, command.oldId.name, command.newId.name).reverse()
+ for (commit in commits) {
+ //get hashes and author data of commit
+ def oldhash = commit.getParent(0).getId().getName()
+ def newhash = commit.getId().getName()
+ def authorIdent = commit.getAuthorIdent()
+ def author = "${authorIdent.name} <${authorIdent.emailAddress}>"
+ //fetch all changed files of the commit
+ def files = JGitUtils.getFilesInCommit(r,commit)
+ def changedFiles = ""
+ for (f in files) {
+ //transform file data to the format which is needed by thebuggenie
+ changedFiles += f.changeType.toString().substring(0,1)+"\t${f.path}\n"
+ }
+ //ok let's submit all information to thebuggenie by calling the client tool
+// def shc = "$tbgCliPath vcs_integration:report_commit $tbgProjectId \"$author\" $newhash \"${commit.fullMessage}\" \"$changedFiles\" $oldhash ${commit.commitTime}"
+ def shc = [tbgCliPath, "vcs_integration:report_commit", tbgProjectId, author, newhash, commit.getFullMessage(), changedFiles, oldhash, commit.getCommitTime()];
+ logger.info("executing in path " + tbgCliDirPath + ": "+shc)
+ shc.execute(null, new File(tbgCliDirPath))
+ }
+}
+
+// close the repository reference
+r.close()