def __lastwatchedcommits(self, args):
        """Implements 'lastwatchedcommits' command.
        Prints all commits on repos watched by 'args.username' with committer timestamp bigger than
        'args.YYYY,MM,DD,hh,mm,ss'.
        """
        # FIXME this code is duplicated:
        now = Timestamp()
        command = args.command + " " + args.username
        if not args.sincelast:
            since = Timestamp(args)
        else:
            try:
                since = Timestamp(p.get().timestamps[command])
            except KeyError as e: # this command gets executed for the first time
                since = now
        o.get().echo(command + " since " + str(since))

        for repo in self.__get_watchlist(args.username):
            pushed = self.__has_been_pushed(repo, since.to_datetime())
            if pushed is not None:
                o.get().echo("%s - %s" % (o.get().red(repo), pushed))
            for commit in self.__get_last_commits(repo, since.to_datetime()):
                o.get().echo("%s - %s" % (o.get().red(repo), commit))

        # Remember this last execution:
        p.get().timestamps[command] = now.data
    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. '*****@*****.**')")
        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. '*****@*****.**')")

        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()