def main():
    m.get().smtplib = smtplib
    o.get().print_function = _print
    cli = Cli(sys.argv[1:], github)
    try:
        cli.run()
    except Exception as e:
        error_msg = "Oops, an error occured.\n" + "\n".join(str(i) for i in e.args) + "\n\n"
        error_msg += traceback.format_exc()
        try:
            o.get().echo(error_msg)
            if cli.errorto is not None:
                m.get().dest.add(cli.errorto)
            if len(m.get().dest):
                # FIXME this code is duplicated:
                email_content = o.get().echoed + "\nSent from %s.\n" % (os.uname()[1])
                m.get().send_result("error", email_content)
                o.get().echo("Sent by e-mail to %s" % ", ".join(m.get().dest))
        except:
            print(error_msg)
        raise
    def run(self):
        parser = argparse.ArgumentParser(description="watch GitHub commits easily")

        parser.add_argument("--version", action="version",
                            version="%(prog)s version " + __version__)

        parser.add_argument("--no-color", action="store_true", help="disable color in output")

        credentials_option = "--credentials"
        parser.add_argument(credentials_option,
                            help="your GitHub login and password (e.g. 'AurelienLourot:password')")

        parser.add_argument("--mailto",
                            help="e-mail address to which the output should be sent in any case "
                            + "(e.g. '[email protected]')")
        parser.add_argument("--mailfrom",
                    help="e-mail server and credentials from which the output should be "
                    + "sent (e.g. 'smtp.googlemail.com:465:[email protected]:password')")
        parser.add_argument("--errorto",
                            help="e-mail address to which the output should be sent in case of an "
                            + "error (e.g. '[email protected]')")

        parser.add_argument(self._persist_option, action="store_true",
                    help="gicowa will keep track of the last commands run in %s" % (p.filename))

        subparsers = parser.add_subparsers(help="available commands")

        descr = "list repos watched by a user"
        parser_watchlist = subparsers.add_parser("watchlist", description=descr, help=descr)
        parser_watchlist.set_defaults(command="watchlist", impl=self.__watchlist)
        self._add_argument_watcher_name(parser_watchlist)

        descr = "list last commits on a repo"
        parser_lastrepocommits = subparsers.add_parser("lastrepocommits", description=descr,
                                                       help=descr)
        parser_lastrepocommits.set_defaults(command="lastrepocommits", impl=self.__lastrepocommits)
        parser_lastrepocommits.add_argument("repo",
                help="repository's full name (e.g. 'AurelienLourot/github-commit-watcher')")
        self._add_arguments_since_committer_timestamp(parser_lastrepocommits)

        descr = "list last commits watched by a user"
        parser_lastwatchedcommits = subparsers.add_parser("lastwatchedcommits", description=descr,
                                                          help=descr)
        parser_lastwatchedcommits.set_defaults(command="lastwatchedcommits",
                                               impl=self.__lastwatchedcommits)
        self._add_argument_watcher_name(parser_lastwatchedcommits)
        self._add_arguments_since_committer_timestamp(parser_lastwatchedcommits)

        args = parser.parse_args(self.__argv)

        if args.mailfrom is not None:
            mailfrom = args.mailfrom.split(":", 3)
            try:
                m.get().server = mailfrom[0]
                m.get().port = mailfrom[1]
                m.get().sender = mailfrom[2]
                m.get().password = mailfrom[3]
            except IndexError as e:
                e.args += ("Bad mailfrom syntax.",)
                raise
        if args.mailto is not None:
            m.get().dest.add(args.mailto)
        self.errorto = args.errorto

        o.get().colored = not args.no_color

        if args.credentials is not None:
            credentials = args.credentials.split(":", 1)
            try:
                self.__github = self.__githublib.Github(credentials[0], credentials[1])
            except IndexError as e:
                e.args += ("Bad credentials' syntax.",)
                raise
        else:
            self.__github = self.__githublib.Github()

        try:
            args.impl(args)
        except self.__githublib.GithubException as e:
            if e.status == 401 and args.credentials is not None:
                e.args += ("Bad credentials?",)
            if e.status == 403 and args.credentials is None:
                e.args += ("API rate limit exceeded? Use the %s option." % (credentials_option),)
            raise
        except socket.gaierror as e:
            e.args += ("No internet connection?",)
            raise

        if len(m.get().dest):
            if o.get().echoed.count("\n") > 1:
                # FIXME this code is duplicated:
                email_content = o.get().echoed + "\nSent from %s.\n" % (os.uname()[1])
                m.get().send_result(args.command, email_content)
                o.get().echo("Sent by e-mail to %s" % ", ".join(m.get().dest))
            else:
                o.get().echo("No e-mail sent.")

        if args.persist:
            p.get().save()