git-egg-author / git-update-meta.scm

(use posix files srfi-1)

(define (usage code)
  (print #<#EOF
usage: git-update-meta

  -h   -help                    Show this message

git-update-meta will ask Git for all files that are managed by
it and put those in the meta-file's FILES entry.  Files that are
unversioned are ignored.

(exit code))

(define (call-with-input-pipe* cmd proc)
  (let* ([p (open-input-pipe cmd)]
         [res (proc p)])
    (unless (zero? (close-input-pipe p))
      (error "Got an error while executing command " cmd))

(define (git-exec cmd)
  (call-with-input-pipe* cmd read-lines ))

(define (ensure-meta-file-exists!)
  (let* ((metas (glob "*.meta")))
    (cond ((null? metas)
           (fprintf (current-error-port)
                    "Error: No meta-file found! Please create one first~%")
           (exit 1))
          ((> (length metas) 1)
           (fprintf (current-error-port)
                    "Error: ~A meta files found. Can only deal with one!~%"
                   (length metas))
           (exit 1))
          (else #t))))

(define (valid-meta-data? port)
  (handle-exceptions exn
    (let ((meta (read-file port)))
      (and (= 1 (length meta))
           (list? (car meta))
           (>= 1 (length (filter (lambda (e)
                                   (eq? 'files (car e)))
                                 (car meta))))))))

(define (update-meta! files-list)
  (let* ((files-list (sort files-list string<?))
	 (meta-file (car (glob "*.meta")))
         (meta-data (read-all meta-file)))
    (unless (call-with-input-string meta-data valid-meta-data?)
      (fprintf (current-error-port) "Error: invalid meta data in ~A~%" meta-file)
      (exit 1))
    (let* ((in (open-input-string meta-data))
           (el #f)
           (end #f))
      (receive (start end)
         (lambda (found)
           (##sys#read in (lambda (class data val)
                            (if (eq? class 'list-info)
                                (if (and el (eq? (car el) 'files))
                                    (found (cdr el) (##sys#slot in 10))
                                    (begin (set! el #f) (set! end (##sys#slot in 10))))
                                (unless el
                                  (set! el (cons data (##sys#slot in 10)))))))
           (values #f end)))
        (print "Updating " meta-file)
        (with-output-to-file meta-file
          (lambda ()
            (if start
                  (display (substring meta-data 0 start))
                  (display #\space)
                  (let ((s (with-output-to-string (lambda ()
                                                    (write files-list)))))
                   (display (substring s 1 (sub1 (string-length s)))))
                  (display (substring meta-data (sub1 end))))
                  (display (substring meta-data 0 (sub1 end)))
                  (display "\n ")
                  (write (cons 'files files-list))
                  (display (substring meta-data (sub1 end)))))))))))

(define (list-egg-files)
  (git-exec "git ls-files"))

(define *short-options* '(#\h))

(define (main args)
  (let loop ((args args))
    (if (null? args)
          (update-meta! (list-egg-files)))
        (let ((arg (car args)))
          (cond ((or (string=? arg "-help")
                     (string=? arg "-h")
                     (string=? arg "--help"))
                 (usage 0))
                ((and (positive? (string-length arg))
                      (char=? #\- (string-ref arg 0)))
                 (if (> (string-length arg) 2)
                     (let ((sos (string->list (substring arg 1))))
                       (if (null? (lset-intersection eq? *short-options* sos))
                           (loop (append (map (cut string #\- <>) sos) (cdr args)))
                           (usage 1)))
                     (usage 1)))
                (else (usage 1)))))))

(main (command-line-arguments))
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.