Ejemplo n.º 1
0
def main():
    if len(sys.argv) == 1:
        cmd_handler(['-h'])
    elif sys.argv[1] == 'commit':
        # commits should not be handled by argparse because the command
        # string must remain intact
        if sys.argv[2] in ('-h', '--help'):
            # however, argparse makes a nice help screen, so we'll use
            # argparse here only if the user asks for help
            parser = argparse.ArgumentParser(
                description='Run a regular git commit, but also log your time.')
            parser.add_argument('--fake', 
                help='Add this commit to the invoice, but don\'t make an actual commit.', 
                action='store_true')
            parser.add_argument('--hours', 
                help='Manually enter the time worked instead of using the timer.',
                nargs='?', 
                default='argparse.SUPPRESS')
            args = parser.parse_args()
        else:
            commands.commit_main(sys.argv)
    else:
        # every other command gets handled by argparse
        try:
            cmd_handler()
        except Exception as e:
            gitime.fprintf(
                "GITIME ERROR: Something has caused gitime to crash. "
                "If the issue persists, please seek help by opening a "
                "ticket on Github at "
                "<https://github.com/jongoodnow/gitime/issues>. "
                "Please include the following error message: ", 
                file=sys.stderr)
            fprintf(e, file=sys.stderr)
Ejemplo n.º 2
0
def commit_main(args):
    # commits are NOT handled by argparse. `args` are passed to this function
    # as they are from sys.argv.
    u = User()
    invid = u.active_invoice_rowid
    if invid == 0:
        fprintf(
            "GITIME ERROR: You do not have an active invoice set. "
            "You won't be able to record your hours without one. "
            "Create an invoice with the command: `gitime invoice -n <invoice "
            "name>` first. Your commit has NOT been made.", file=sys.stderr)
        sys.exit()
    inv = Invoice(invid)
    raw_hours = parse_hours_flag(args)
    if raw_hours is not False:
        hours = round(raw_hours / inv.rounding) * inv.rounding
    else:
        hours = u.time_tracked(inv)
        if hours <= 0:
            fprintf(
                "GITIME ERROR: You didn't specify a number of hours, and the "
                "timer hasn't recorded anything. Run this command with the "
                "`--hours <hour count>` flag, or use the timer to track your "
                "time. Your commit has NOT been made."), file=sys.stderr)
            sys.exit()
        u.reset_timer()
    message = parse_commit_message(args)
    if not message:
        fprintf("GITIME ERROR: Could not find a message in your commit.", 
            file=sys.stderr)
        sys.exit()
Ejemplo n.º 3
0
def timer_main(args):
    u = User()
    if not args.force:
        if u.active_invoice_rowid == 0:
            fprintf(
                "WARNING: You do not have an active invoice set. "
                "You won't be able to record your hours without one. "
                "Create an invoice with the command: `gitime invoice -n "
                "<invoice name>` first, or suppress this warning by running "
                "the timer with the --force flag.", 
            file=sys.stderr)
            sys.exit()
    if args.action == 'start':
        u.start_timer()
        fprintf('Timer started at %s' %str(datetime.now()))
    elif args.action == 'pause':
        u.pause_timer()
        fprintf('Timer paused at %s' %str(datetime.now()))
    elif args.action == 'reset':
        u.reset_timer()
    elif args.action == 'status':
        inv = Invoice(u.active_invoice_rowid)
        if u.timer_running:
            status = 'has been running since %s.' %str(
                datetime.fromtimestamp(u.timer_start))
        else:
            status = 'is not running.'
        fprintf('The timer %s' %status)
        fprintf('Total hours tracked: %.2f' %(u.time_tracked(inv)))
Ejemplo n.º 4
0
 def set_rate(self, r):
     try:
         r = float(r)
     except ValueError:
         fprintf('Rates must be provided in the form of a number.', 
             file=sys.stderr)
         sys.exit()
     self.rate = r
     db.update(lambda c: c.execute("""
         UPDATE invoice SET rate=? WHERE rowid=?
     """, (self.rate, self.rowid)))
Ejemplo n.º 5
0
def invoice_main(args):
    u = User()
    if hasattr(args, 'name'):
        if args.new:
            kwargs = {'new': True}
            if hasattr(args, 'rate'):
                kwargs['rate'] = args.rate
            if hasattr(args, 'round'):
                kwargs['rounding'] = args.round
            inv = Invoice(args.name, **kwargs)
            inv.set_active()
            fprintf("Future commits will now be sent to the invoice %s." 
                %inv.name)
        else:
            try:
                inv = Invoice(args.name)
            except InvoiceNotFound:
                if raw_input(
                    "That invoice doesn't exist. Make a new one? [Y/n] "
                ) == 'n':
                    sys.exit()
                inv = Invoice(args.name, new=True)
            if hasattr(args, 'rate'):
                inv.set_rate(args.rate)
            if hasattr(args, 'round'):
                inv.set_rounding(args.round)
            if u.active_invoice_rowid != inv.rowid:
                inv.set_active()
                fprintf("Future commits will now be sent to the invoice %s." 
                    %inv.name)
    else:
        if db.invoice_count() == 0:
            fprintf("You do not have any invoices yet! Create one with `gitime "
                "invoice -n <invoice name>`.")
        else:
            inv = Invoice(u.active_invoice_rowid)
            if hasattr(args, 'rate'):
                inv.set_rate(args.rate)
            if hasattr(args, 'round'):
                inv.set_rounding(args.round)
    if args.list:
        count = db.invoice_count()
        noun = 'invoice' if count == 1 else 'invoices'
        fprintf("You have %d %s:" %(count, noun))
        for invoice in db.query_all_invoices():
            if invoice[3] == u.active_invoice_rowid:
                active = " (active)"
            else:
                active = ""
            fprintf(invoice[0], active)
Ejemplo n.º 6
0
def export_invoice_main(args):
    if hasattr(args, 'invoice'):
        try:
            inv = Invoice(args.invoice)
        except InvoiceNotFound:
            fprintf("That invoice does not exist.", file=sys.stderr)
            sys.exit()
    else:
        u = User()
        if u.active_invoice_rowid == 0:
            fprintf("You do not have an active invoice set. Create one with "
                "`gitime invoice -n <invoice name> first.", file=sys.stderr)
            sys.exit()
        inv = Invoice(u.active_invoice_rowid)
Ejemplo n.º 7
0
def parse_hours_flag(args):
    """ If the `--hours` flag was used, get the time, and remove 
        the flag and the time from the args list.
        Return FALSE if the flag was not present.
    """
    try:
        pos = args.index('--hours')
    except ValueError:
        return False
    else:
        hours = args[pos + 1]
        try:
            hours = float(hours)
        except ValueError:
            fprintf("GITIME ERROR: %s is not a valid amount of hours. Your "
                "commit was NOT made. Try again." %hours, file=sys.stderr)
            sys.exit()
        else:
            del args[pos + 1]
            del args[pos]
            return hours
Ejemplo n.º 8
0
def status_main(args):
    if hasattr(args, 'invoice'):
        inv = Invoice(args.invoice)
    else:
        u = User()
        invid = u.active_invoice_rowid
        if invid == 0:
            fprintf("You do not have any invoices yet! Create one with `gitime "
                "invoice -n <invoice name>`.")
            sys.exit()
        inv = Invoice(u.active_invoice_rowid)
    total_hours = inv.total_hours()
    hourstr = 'hour' if total_hours == 1 else 'hours'
    print(textwrap.dedent("""\
        On invoice %s
        Total Time Worked: %g %s
        Total Charges:     $%.2f
        Charges:""" 
    %(inv.name, total_hours, hourstr, inv.total_earnings())))
    commits = inv.get_commit_meta()
    if not commits:
        fprintf("No charges yet!")
    else:
        for com in commits:
            date = (datetime.fromtimestamp(com[1])).strftime('%m-%d-%Y')
            wspace1 = (17 - len(date)) * " "
            hourstr = 'hour' if com[2] == 1 else 'hours'
            hours = "%g %s" %(com[2], hourstr)
            wspace2 = (14 - len(hours)) * " "
            message = com[0]
            fprintf(date, wspace1, hours, wspace2, message)
Ejemplo n.º 9
0
def parse_commit_message(args):
    """ Find the commit message in the commit command.
        Messages may be formatted like:
        * `-m "some message"`
        * `--message "some message"`
        * `--message="some message"`
        Single quotes are allowed too.
        `args` is a list that should be formatted exactly as sys.argv
    """
    reg = re.compile(
        r"(\-\w*m\w*|\-\-message)(\s*|(='(?:\\.|[^'])*'|\"(?:\\.|[^\"])*\"))")
    scan = [index for index, val in enumerate(args) 
        for mat in [reg.search(val)] if mat]
    if not scan:
        return False
    if len(scan) > 1:
        fprintf("GITIME ERROR: Your commit contains more than one message. "
            "Your commit was NOT made. Try again.", file=sys.stderr)
        sys.exit()
    index = scan[0]
    # check if the format is `--message="some message"`
    format_reg = re.search(r"='((\\.|[^'])*?)'|\"((\\.|[^\"])*?)\"", 
        args[index])
    if format_reg is not None:
        return format_reg.group().strip('=').strip('"').strip("'")
    elif len(args) < index + 2:
        fprintf("GITIME ERROR: Your commit doesn't contain a message. Your "
            "commit was NOT made. Try again.", file=sys.stderr)
        sys.exit()
    else:
        ret = args[index + 1]
        # escape unescaped quotes so that we can add quotes around the message
        args[index + 1] = re.sub(r'(?<!\\)(?:\\\\)*"', '\\"', args[index + 1])
        # add quotes to the message so that git can understand it 
        # when the command is run
        args[index + 1] = "".join(['"', args[index + 1], '"'])
        return ret
Ejemplo n.º 10
0
 def __init__(self, unique, new=False, rate=None, rounding=None, userid=1):
     """ Invoices can be instantiated from a rowid or a name.
         If the name isn't already in the database a new one
         will be created if `new` is true. Otherwise the program 
         halts. If instantiated from a rowid, using a rowid that 
         does not exist will throw an exception. `rate` and 
         `rounding` args unnecessary if querying by rowid. 
         `rate` and `rounding` default to user values.
     """
     self.user = User(userid)
     meta = db.query_invoice(unique)
     if meta:
         if new:
             print("An invoice with the name %s already exists. You can't "
                 "make a new one with that name." %unique, file=sys.stderr)
             sys.exit()
         self.name = meta[0]
         self.rate = meta[1]
         self.rounding = meta[2]
         self.rowid = meta[3] if len(meta) == 4 else unique
     else:
         # this will only happen if `unique` is a name
         # if `unique` is a rowid, an exception is raised
         # on the query.
         if not new:
             raise InvoiceNotFound
         self.name = unique
         if rate is None and self.user.rate == 0:
             fprintf("WARNING: Your default hourly rate is set to zero. This"
                 " means that no earnings will be recorded. You can set your"
                 " default rate with `gitime set -r <rate>` or set the rate "
                 "for this invoice with `gitime invoice <invoice name> -r "
                 "<rate>`.")
         self.rate = rate if rate is not None else self.user.rate
         self.rounding = (rounding if rounding is not None 
             else self.user.rounding)
         self.rowid = db.insert_invoice(self.name, self.rate, self.rounding)
Ejemplo n.º 11
0
def settings_main(args):
    u = User()
    if hasattr(args, 'rate'):
        u.set_rate(args.rate)
        fprintf("The rate of $%s per hour will be applied to all new invoices." 
            %args.rate)
    if hasattr(args, 'round'):
        u.set_rounding(args.round)
        fprintf("Hours will be rounded to the nearest %s on all new invoices" 
            %args.round)
    if args.list:
        fprintf(textwrap.dedent("""\
            Your default values for all invoices created in the future:
            Hourly Rate: $%.2f
            Round hours to the nearest %g""" 
        %(u.rate, u.rounding)))
Ejemplo n.º 12
0
            fprintf(
                "GITIME ERROR: You didn't specify a number of hours, and the "
                "timer hasn't recorded anything. Run this command with the "
                "`--hours <hour count>` flag, or use the timer to track your "
                "time. Your commit has NOT been made."), file=sys.stderr)
            sys.exit()
        u.reset_timer()
    message = parse_commit_message(args)
    if not message:
        fprintf("GITIME ERROR: Could not find a message in your commit.", 
            file=sys.stderr)
        sys.exit()
    com = Commit(message=message,
                 hours=hours,
                 invoice=u.active_invoice_rowid)
    fprintf("GITIME: Your commit has been logged in invoice %s." %inv.name)
    if '--fake' not in args:
        fprintf("GITIME: Running your commit now...")
        args[0] = 'git'
        os.system(" ".join(args))


def export_invoice_main(args):
    if hasattr(args, 'invoice'):
        try:
            inv = Invoice(args.invoice)
        except InvoiceNotFound:
            fprintf("That invoice does not exist.", file=sys.stderr)
            sys.exit()
    else:
        u = User()