summaryrefslogtreecommitdiffstats
path: root/roles/git/hooks/files/util.py
diff options
context:
space:
mode:
Diffstat (limited to 'roles/git/hooks/files/util.py')
-rw-r--r--roles/git/hooks/files/util.py153
1 files changed, 153 insertions, 0 deletions
diff --git a/roles/git/hooks/files/util.py b/roles/git/hooks/files/util.py
new file mode 100644
index 000000000..f35019634
--- /dev/null
+++ b/roles/git/hooks/files/util.py
@@ -0,0 +1,153 @@
+# General Utility Functions used in our Git scripts
+#
+# Copyright (C) 2008 Owen Taylor
+# Copyright (C) 2009 Red Hat, Inc
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, If not, see
+# http://www.gnu.org/licenses/.
+
+import os
+import sys
+from subprocess import Popen
+import tempfile
+import time
+
+def die(message):
+ print >>sys.stderr, message
+ sys.exit(1)
+
+# This cleans up our generation code by allowing us to use the same indentation
+# for the first line and subsequent line of a multi-line string
+def strip_string(str):
+ start = 0
+ end = len(str)
+ if len(str) > 0 and str[0] == '\n':
+ start += 1
+ if len(str) > 1 and str[end - 1] == '\n':
+ end -= 1
+
+ return str[start:end]
+
+# How long to wait between mails (in seconds); the idea of waiting
+# is to try to make the sequence of mails we send out in order
+# actually get delivered in order. The waiting is done in a forked
+# subprocess and doesn't stall completion of the main script.
+EMAIL_DELAY = 5
+
+# Some line that can never appear in any email we send out
+EMAIL_BOUNDARY="---@@@--- gnome-git-email ---@@@---\n"
+
+# Run in subprocess
+def _do_send_emails(email_in):
+ email_files = []
+ current_file = None
+ last_line = None
+
+ # Read emails from the input pipe and write each to a file
+ for line in email_in:
+ if current_file is None:
+ current_file, filename = tempfile.mkstemp(suffix=".mail", prefix="gnome-post-receive-email-")
+ email_files.append(filename)
+
+ if line == EMAIL_BOUNDARY:
+ # Strip the last line if blank; see comment when writing
+ # the email boundary for rationale
+ if last_line.strip() != "":
+ os.write(current_file, last_line)
+ last_line = None
+ os.close(current_file)
+ current_file = None
+ else:
+ if last_line is not None:
+ os.write(current_file, last_line)
+ last_line = line
+
+ if current_file is not None:
+ if last_line is not None:
+ os.write(current_file, last_line)
+ os.close(current_file)
+
+ # We're done interacting with the parent process, the rest happens
+ # asynchronously; send out the emails one by one and remove the
+ # temporary files
+ for i, filename in enumerate(email_files):
+ if i != 0:
+ time.sleep(EMAIL_DELAY)
+
+ f = open(filename, "r")
+ process = Popen(["/usr/sbin/sendmail", "-t"],
+ stdout=None, stderr=None, stdin=f)
+ process.wait()
+ f.close()
+
+ os.remove(filename)
+
+email_file = None
+
+# Start a new outgoing email; returns a file object that the
+# email should be written to. Call end_email() when done
+def start_email():
+ global email_file
+ if email_file is None:
+ email_pipe = os.pipe()
+ pid = os.fork()
+ if pid == 0:
+ # The child
+
+ os.close(email_pipe[1])
+ email_in = os.fdopen(email_pipe[0])
+
+ # Redirect stdin/stdout/stderr to/from /dev/null
+ devnullin = os.open("/dev/null", os.O_RDONLY)
+ os.close(0)
+ os.dup2(devnullin, 0)
+
+ devnullout = os.open("/dev/null", os.O_WRONLY)
+ os.close(1)
+ os.dup2(devnullout, 1)
+ os.close(2)
+ os.dup2(devnullout, 2)
+ os.close(devnullout)
+
+ # Fork again to daemonize
+ if os.fork() > 0:
+ sys.exit(0)
+
+ try:
+ _do_send_emails(email_in)
+ except Exception:
+ import syslog
+ import traceback
+
+ syslog.openlog(os.path.basename(sys.argv[0]))
+ syslog.syslog(syslog.LOG_ERR, "Unexpected exception sending mail")
+ for line in traceback.format_exc().strip().split("\n"):
+ syslog.syslog(syslog.LOG_ERR, line)
+
+ sys.exit(0)
+
+ email_file = os.fdopen(email_pipe[1], "w")
+ else:
+ # The email might not end with a newline, so add one. We'll
+ # strip the last line, if blank, when emails, so the net effect
+ # is to add a newline to messages without one
+ email_file.write("\n")
+ email_file.write(EMAIL_BOUNDARY)
+
+ return email_file
+
+# Finish an email started with start_email
+def end_email():
+ global email_file
+ email_file.flush()