diff --git a/rbtools/postreview.py b/rbtools/postreview.py
--- a/rbtools/postreview.py
+++ b/rbtools/postreview.py
@@ -447,6 +447,22 @@ class ReviewBoardServer(object):
             field: value,
         })
 
+    def get_bugs(self):
+        """
+        Returns the list of bugs closed in this review.
+        """
+        review_request = self.api_get('api/json/reviewrequests/%s/' %
+                                      options.rid)
+        return review_request['review_request']['bugs_closed']
+
+    def get_description(self):
+        """
+        Returns the description for this review.
+        """
+        review_request = self.api_get('api/json/reviewrequests/%s/' %
+                                      options.rid)
+        return review_request['review_request']['description']
+
     def get_review_request(self, rid):
         """
         Returns the review request with the specified ID.
@@ -468,6 +484,39 @@ class ReviewBoardServer(object):
         rsp = self.api_get('/api/json/repositories/%s/info/' % rid)
         return rsp['info']
 
+    def get_reviewers(self):
+        """
+        Returns the list of people who reviewed the current change.
+        """
+        reviewers = []
+        reviews = self.api_get('/api/json/reviewrequests/%s/reviews/' %
+                               options.rid)
+        for review in reviews['reviews']:
+           reviewers.append(review['user']['username'])
+
+        return reviewers
+
+    def get_approvers(self):
+        """
+        Returns the list of people who approved the current change.
+        """
+        approvers = []
+        reviews = self.api_get('/api/json/reviewrequests/%s/reviews/' %
+                               options.rid)
+        for review in reviews['reviews']:
+           if review['ship_it'] is 1:
+               approvers.append(review['user']['username'])
+
+        return approvers
+
+    def get_review_url(self, rid):
+        """
+        Returns the URL to the current review.
+        """
+        review_request = self.get_review_request(rid)
+        request_url = 'r/' + str(review_request['id'])
+        return self._make_url(request_url)
+
     def save_draft(self, review_request):
         """
         Saves a draft of a review request.
@@ -476,6 +525,18 @@ class ReviewBoardServer(object):
                       review_request['id'])
         debug("Review request draft saved")
 
+    def add_review(self, body_top, body_bottom='', ship_it=False):
+        """
+        Add a review to a review request.
+        """
+        review_request = self.get_review_request(options.rid)
+        self.api_post('api/json/reviewrequests/%s/reviews/draft/publish/' %
+                      review_request['id'], {
+            'shipit': str(ship_it),
+            'body_top': body_top,
+            'body_bottom': body_bottom,
+        })
+
     def upload_diff(self, review_request, diff_content, parent_diff_content):
         """
         Uploads a diff to a Review Board server.
@@ -505,6 +566,22 @@ class ReviewBoardServer(object):
         self.api_post('api/json/reviewrequests/%s/diff/new/' %
                       review_request['id'], fields, files)
 
+    def close(self, type):
+        """
+        Closes a review.
+        """
+        debug("Closing with type %s" % type)
+        if not options.rid:
+            print "Can't close without a request ID."
+            sys.exit(1)
+        else:
+            review_request = self.get_review_request(options.rid)
+
+        debug('Using API: api/json/reviewrequests/%s/close/%s/' %
+              (review_request['id'], type))
+        self.api_post('api/json/reviewrequests/%s/close/%s/' %
+                      (review_request['id'], type))
+
     def publish(self, review_request):
         """
         Publishes a review request.
@@ -661,8 +738,8 @@ class ReviewBoardServer(object):
 
 class SCMClient(object):
     """
-    A base representation of an SCM tool for fetching repository information
-    and generating diffs.
+    A base representation of an SCM tool for fetching repository information,
+    checking in revisions and generating diffs.
     """
     def get_repository_info(self):
         return None
@@ -727,6 +804,12 @@ class SCMClient(object):
 
         return None
 
+    def submit(self, server, changenum, files):
+        """
+        Submits the code into the repository.
+        """
+        return None
+
 
 class CVSClient(SCMClient):
     """
@@ -792,6 +875,12 @@ class CVSClient(SCMClient):
         return execute(["cvs", "diff", "-uN"] + params,
                         extra_ignore_errors=(1,))
 
+    def submit(self, server, changenum, files):
+        """
+        Submits the code into the repository.
+        """
+        return None
+
 
 class ClearCaseClient(SCMClient):
     """
@@ -1099,6 +1188,12 @@ class ClearCaseClient(SCMClient):
         ostr = ''.join(o)
         return (ostr, None) # diff, parent_diff (not supported)
 
+    def submit(self, server, changenum, files):
+        """
+        Submits the code into the repository.
+        """
+        return None
+
 
 class SVNClient(SCMClient):
     """
@@ -1341,6 +1436,21 @@ class SVNClient(SCMClient):
         # strip off ending newline, and return it as the second component
         return [s.split('\n')[0], '\n']
 
+    def submit(self, server, changenum, files):
+        """
+        Submits the code into the repository.
+        """
+
+        message  = "Review: "       + server.get_review_url(options.rid) + "\n"
+        message += "Bugs: "         + ", ".join(server.get_bugs()) + '\n'
+        message += "Reviewers: "    + ", ".join(server.get_reviewers()) + "\n"
+        message += "Approvers: "    + ", ".join(server.get_approvers()) + "\n"
+        message += "\nDescription:\n" + server.get_description() + "\n\n"
+
+        debug("Begin Subversion Submit")
+        svn_ci_message = execute(["svn", "ci", "-m", message, " ".join(files)])
+        debug("Subversion Messages:\n%s" % svn_ci_message)
+        return svn_ci_message
 
 class PerforceClient(SCMClient):
     """
@@ -1876,6 +1986,12 @@ class PerforceClient(SCMClient):
             # XXX: This breaks on filenames with spaces.
             return where_output[-1]['data'].split(' ')[2].strip()
 
+    def submit(self, server, changenum, files):
+        """
+        Submits the code into the repository.
+        """
+        return None
+
 
 class MercurialClient(SCMClient):
     """
@@ -2011,6 +2127,12 @@ class MercurialClient(SCMClient):
 
         return execute(["hg", "diff", "-r", r1, "-r", r2])
 
+    def submit(self, server, changenum, files):
+        """
+        Submits the code into the repository.
+        """
+        return None
+
 
 class GitClient(SCMClient):
     """
@@ -2293,6 +2415,12 @@ class GitClient(SCMClient):
 
             return self.make_diff(r1, r2)
 
+    def submit(self, server, changenum, files):
+        """
+        Submits the code into the repository.
+        """
+        return None
+
 
 SCMCLIENTS = (
     SVNClient(),
@@ -2505,11 +2633,7 @@ def tempt_fate(server, tool, changenum, diff_content=None,
     if options.publish:
         server.publish(review_request)
 
-    request_url = 'r/' + str(review_request['id'])
-    review_url = urljoin(server.url, request_url)
-
-    if not review_url.startswith('http'):
-        review_url = 'http://%s' % review_url
+    review_url = server.get_review_url(review_request['id'])
 
     print "Review request #%s posted." % (review_request['id'],)
     print
@@ -2526,6 +2650,15 @@ def parse_options(args):
                       dest="publish", action="store_true", default=PUBLISH,
                       help="publish the review request immediately after "
                            "submitting")
+    parser.add_option("-s", "--submit",
+                      dest="submit", action="store_true", default=False,
+                      help="close the review request as submitted "
+                           "and submit the review if supported. "
+                           "Files on the command line will be passed to "
+                           "the SCM tool.")
+    parser.add_option("--discard",
+                      dest="discard", action="store_true", default=False,
+                      help="discard the review request")
     parser.add_option("-r", "--review-request-id",
                       dest="rid", metavar="ID", default=None,
                       help="existing review request ID to update")
@@ -2775,6 +2908,9 @@ def main():
                 fp.close()
             except IOError, e:
                 die("Unable to open diff filename: %s" % e)
+    elif options.submit or options.discard:
+        diff = None
+        parent_diff = None
     else:
         diff, parent_diff = tool.diff(args)
 
@@ -2785,12 +2921,23 @@ def main():
         print diff
         sys.exit(0)
 
+    if options.submit and options.discard:
+        print "You can't submit and discard a review."
+        sys.exit(1)
+
     # Let's begin.
     server.login()
 
-    review_url = tempt_fate(server, tool, changenum, diff_content=diff,
-                            parent_diff_content=parent_diff,
-                            submit_as=options.submit_as)
+    if options.submit:
+        scm_message = tool.submit(server, changenum, args)
+        server.add_review(scm_message)
+        server.close("submitted")
+    elif options.discard:
+        server.close("discarded")
+    else:
+        review_url = tempt_fate(server, tool, changenum, diff_content=diff,
+                                parent_diff_content=parent_diff,
+                                submit_as=options.submit_as)
 
     # Load the review up in the browser if requested to:
     if options.open_browser:
