def send_upstream(self, downstream, upstream):
        """
        Sends the change indicated by the comment upstream.

        @param downstream - gerrit.Remote downstream object
        @param upstream - gerrit.Remote upstream object

        """

        # Check if upstream project before doing anything.
        if not self.is_upstream_project():
            return

        ssh = downstream.SSH()

        # Check to see if comment indicates a change is upstream ready
        if not self.is_upstream_indicated():
            logger.debug("Change %s: Upstream not indicated" % self.change_id)
            return

        # Grab all of the approvals
        approvals = self.get_approvals(downstream.SSH())

        # Check to see if comment has necessary approvals.
        if self.is_forced():
            if not self.is_release_approved(approvals):
                msg = "Could not send to upstream: Release not approved."
                logger.debug("Change %s: %s" % (self.change_id, msg))
                ssh.exec_once('gerrit review -m %s %s'
                              % (pipes.quote(msg), self.revision))
                return
            msg = ("***WARNING***\n%s (%s) has requested a forced upstream "
                   "push. Bypassing all votes except for Release...\n\n"
                   "Current votes are:\n\n%s"
                   % (self._data['author']['name'],
                      self._data['author']['email'],
                      self.stringify_approvals(approvals)))
            logger.debug("Change %s: %s" % (self.change_id, msg))
            ssh.exec_once('gerrit review -m %s %s'
                          % (pipes.quote(msg), self.revision))
        else:
            if not self.is_upstream_approved(approvals):
                msg = ("Could not send to upstream: One or more labels"
                       " not approved.")
                logger.debug("Change %s: %s" % (self.change_id, msg))
                ssh.exec_once('gerrit review -m %s %s'
                              % (pipes.quote(msg), self.revision))
                return

        # Do some git stuffs to push upstream
        logger.debug("Change %s: Sending to upstream" % self.change_id)

        repo_dir = '~/tmp'
        repo_dir = os.path.expanduser(repo_dir)
        repo_dir = os.path.abspath(repo_dir)

        # Add uuid, want a unique directory here
        uuid_dir = str(uuid4())
        repo_dir = os.path.join(repo_dir, uuid_dir)

        # Make Empty directory - We want this to stop and fail on OSError
        if not os.path.isdir(repo_dir):
            os.makedirs(repo_dir)
            logger.debug(
                "Change %s: Created directory %s" % (self.change_id, repo_dir)
            )

        # Save the current working directory
        old_cwd = os.getcwd()

        try:
            # Change to newly created directory.
            os.chdir(repo_dir)

            # Init the cwd
            git.init()

            # Add the remotes for upstream and downstream
            remote_url = "ssh://%[email protected]%s:%s/%s"
            git.add_remote('downstream', remote_url % (downstream.username,
                                                       downstream.host,
                                                       downstream.port,
                                                       self.project))

            # Figure out what user we will pose as
            # This every upstream user sharing the same key is kinda shady.
            # Default back to the configured user if username doesnt exist.
            # should fail in this case
            username = self.patchset_uploader_username
            name = self.patchSet_uploader_name
            email = self.patchset_uploader_email
            if not username:
                logger.debug("Change %s: Unable to use author credentials."
                             " Defaulting to configured credentials."
                             % self.change_id)
                username = upstream.username
                name = self._conf['git-config']['name']
                email = self._conf['git-config']['email']

            git.add_remote('upstream', remote_url % (username,
                                                     upstream.host,
                                                     upstream.port,
                                                     self.project))
            logger.debug('Change %s: Sending upstream as '
                         'username %s, email %s, name %s'
                         % (self.change_id, username, email, name))
            try:
                env = get_review_env()

                # Set committer info
                git.set_config('user.email', email)
                git.set_config('user.name', name)

                # Download  specific change to local
                args = ['git-review', '-r', 'downstream', '-d',
                        '%s,%s' % (self.change_id, self.patchset_id)]
                logger.debug('Change %s: running: %s'
                             % (self.change_id, ' '.join(args)))
                out = subprocess.check_output(args,
                                              stderr=subprocess.STDOUT,
                                              env=env)
                logger.debug("Change %s: %s" % (self.change_id, out))

                # Send downloaded change to upstream
                args = ['git-review', '-R', '-y', '-r', 'upstream',
                        self.branch, '-t', self.topic]
                logger.debug('Change %s: running: %s'
                             % (self.change_id, ' '.join(args)))
                out = subprocess.check_output(args,
                                              stderr=subprocess.STDOUT,
                                              env=env)
                logger.debug("Change %s: %s" % (self.change_id, out))

                upstream_url = self.get_upstream_url(upstream)

                msg = 'Sent to upstream: %s' % (upstream_url)
                # Send comment to downstream gerrit with link to change in
                # upstream gerrit
                ssh.exec_once('gerrit review -m %s %s'
                              % (pipes.quote(msg), self.revision))

            except subprocess.CalledProcessError as e:
                msg = "Could not send to upstream:\n%s" % e.output
                ssh.exec_once('gerrit review -m %s %s'
                              % (pipes.quote(msg), self.revision))
                logger.error("Change %s: Unable to send to upstream"
                             % self.change_id)
                logger.error("Change %s: %s" % (self.change_id, out))

            except Exception:
                msg = 'Could not send to upstream: Error running git-review'
                ssh.exec_once('gerrit review -m %s %s'
                              % (pipes.quote(msg), self.revision))
                logger.exception("Change %s: Unable to send to upstream"
                                 % self.change_id)

        finally:
            # Change to old current working directory
            os.chdir(old_cwd)

            # Attempt to clean up created directory
            shutil.rmtree(repo_dir)
    def _config(self, remote, conf, groups):
        """
        Builds the groups file and project.config file for a project.

        @param remote - gerrit.Remote object
        @param conf - Dict containing git config information
        @param groups - List of groups

        """
        if not self.config:
            return

        msg = "Project %s: Configuring." % self.name
        logger.info(msg)
        print msg

        repo_dir = '~/tmp'
        repo_dir = os.path.expanduser(repo_dir)
        repo_dir = os.path.abspath(repo_dir)

        uuid_dir = str(uuid4())
        repo_dir = os.path.join(repo_dir, uuid_dir)

        # Make Empty directory - We want this to stop and fail on OSError
        logger.debug(
            "Project %s: Creating directory %s" % (self.name, repo_dir)
        )
        os.makedirs(repo_dir)

        # Save the current working directory
        old_cwd = os.getcwd()

        origin = 'origin'

        try:
            # Change cwd to that repo
            os.chdir(repo_dir)

            # Git init empty directory
            git.init()

            # Add remote origin
            ssh_url = 'ssh://%[email protected]%s:%s/%s' % (
                remote.username,
                remote.host,
                remote.port,
                self.name
            )

            git.add_remote(origin, ssh_url)

            # Fetch refs/meta/config for project
            refspec = 'refs/meta/config:refs/remotes/origin/meta/config'
            git.fetch(origin, refspec)

            # Checkout refs/meta/config
            git.checkout_branch('meta/config')

            # Get md5 of existing config
            _file = os.path.join(repo_dir, 'project.config')
            contents = ''
            try:
                with open(_file, 'r') as f:
                    contents = f.read()
            except IOError:
                pass
            existing_md5 = hashlib.md5(contents).hexdigest()

            # Get md5 of new config
            with open(self.config, 'r') as f:
                contents = f.read()
            new_md5 = hashlib.md5(contents).hexdigest()

            msg = "Project %s: Md5 comparision\n%s\n%s"
            msg = msg % (self.name, existing_md5, new_md5)
            logger.debug(msg)
            print msg

            # Only alter if checksums do not match
            if existing_md5 != new_md5:

                logger.debug(
                    "Project %s: config md5's are different." % self.name
                )

                # Update project.config file
                _file = os.path.join(repo_dir, 'project.config')
                with open(_file, 'w') as f:
                    f.write(contents)

                # Update groups file
                group_contents = groups_file_contents(groups)
                _file = os.path.join(repo_dir, 'groups')
                with open(_file, 'w') as f:
                    f.write(group_contents)

                # Git config user.email
                git.set_config('user.email', conf['git-config']['email'])

                # Git config user.name
                git.set_config('user.name', conf['git-config']['name'])

                # Add groups and project.config
                git.add(['groups', 'project.config'])

                # Git commit
                git.commit(message='Setting up %s' % self.name)

                # Git push
                git.push(origin, refspecs='meta/config:refs/meta/config')
                logger.info("Project %s: pushed configuration." % self.name)

            else:
                msg = "Project %s: config unchanged." % self.name
                logger.info(msg)
                print msg

        finally:
            # Change to old current working directory
            os.chdir(old_cwd)

            # Attempt to clean up created directory
            shutil.rmtree(repo_dir)