Jaypore CI

> Jaypore CI: Minimal, Offline, Local CI system.
Log | Files | Refs | README | LICENSE

cron_parser.go (1584B)


      1 package jci
      2 
      3 import (
      4 	"bufio"
      5 	"errors"
      6 	"fmt"
      7 	"io"
      8 	"os"
      9 	"path/filepath"
     10 	"strings"
     11 )
     12 
     13 // LoadCronEntries opens .jci/crontab (if it exists) and parses all entries.
     14 func LoadCronEntries(repoRoot string) ([]CronEntry, error) {
     15 	cronPath := filepath.Join(repoRoot, ".jci", "crontab")
     16 	f, err := os.Open(cronPath)
     17 	if err != nil {
     18 		if os.IsNotExist(err) {
     19 			return nil, nil
     20 		}
     21 		return nil, err
     22 	}
     23 	defer f.Close()
     24 
     25 	return parseCronEntries(f)
     26 }
     27 
     28 func parseCronEntries(r io.Reader) ([]CronEntry, error) {
     29 	scanner := bufio.NewScanner(r)
     30 	var entries []CronEntry
     31 	lineNum := 0
     32 
     33 	for scanner.Scan() {
     34 		lineNum++
     35 		raw := strings.TrimSpace(scanner.Text())
     36 		if raw == "" || strings.HasPrefix(raw, "#") {
     37 			continue
     38 		}
     39 
     40 		schedule, command, err := splitCronLine(raw)
     41 		if err != nil {
     42 			return nil, fmt.Errorf("line %d: %w", lineNum, err)
     43 		}
     44 
     45 		entries = append(entries, CronEntry{
     46 			Line:     lineNum,
     47 			Schedule: schedule,
     48 			Command:  command,
     49 			Raw:      raw,
     50 		})
     51 	}
     52 
     53 	if err := scanner.Err(); err != nil {
     54 		return nil, err
     55 	}
     56 
     57 	return entries, nil
     58 }
     59 
     60 func splitCronLine(raw string) (string, string, error) {
     61 	if strings.HasPrefix(raw, "@") {
     62 		parts := strings.Fields(raw)
     63 		if len(parts) < 2 {
     64 			return "", "", errors.New("missing command for cron entry")
     65 		}
     66 		return parts[0], strings.Join(parts[1:], " "), nil
     67 	}
     68 
     69 	parts := strings.Fields(raw)
     70 	if len(parts) < 6 {
     71 		return "", "", errors.New("cron entry must have 5 time fields and a command")
     72 	}
     73 
     74 	schedule := strings.Join(parts[:5], " ")
     75 	command := strings.Join(parts[5:], " ")
     76 	return schedule, command, nil
     77 }