#lang racket/base (require rackunit racket/file git) (define tmp (make-temporary-file "racket-git-test~a" 'directory)) (dynamic-wind void (lambda () (make-directory (build-path tmp "sub")) (parameterize ([current-directory tmp]) (git 'init) (check-true (git-repository?)) (check-equal? (git-current-branch) "master") (check-true (git-clean?)) (git 'config "user.name" "Racket Git Test") (git 'config "user.email" "racket-git-test@example.invalid") (check-equal? (git-config "user.name") "Racket Git Test") (call-with-output-file ".gitignore" #:exists 'truncate/replace (lambda (out) (displayln "ignored.txt" out))) (call-with-output-file "ignored.txt" #:exists 'truncate/replace (lambda (out) (displayln "ignored" out))) (call-with-output-file (build-path "sub" "hello.txt") #:exists 'truncate/replace (lambda (out) (displayln "hello" out))) (check-equal? (git-status-lines) '("?? .gitignore" "?? sub/hello.txt")) (define status-output (open-output-string)) (define displayed-status (parameterize ([current-output-port status-output]) (dgit 'status))) (check-equal? displayed-status (git 'status)) (check-equal? (get-output-string status-output) "New - .gitignore\nNew - sub/hello.txt\n") (check-false (regexp-match? #rx"ignored[.]txt" (get-output-string status-output))) (parameterize ([current-directory (build-path tmp "sub")]) (git 'add "hello.txt")) (check-equal? (git-status-lines) '("?? .gitignore" "A sub/hello.txt")) (git 'add ".gitignore") (define first (git-commit "initial commit")) (check-equal? (string-length first) 40) (check-true (git-clean?)) (check-equal? (git 'diff) "") (check-equal? (git 'diff '--cached) "") (call-with-output-file (build-path "sub" "hello.txt") #:exists 'truncate/replace (lambda (out) (displayln "changed" out))) (define worktree-diff (git 'diff)) (check-true (regexp-match? #rx"-hello" worktree-diff)) (check-true (regexp-match? #rx"[+]changed" worktree-diff)) (check-equal? (git 'diff '--cached) "") (define diff-output (open-output-string)) (parameterize ([current-output-port diff-output]) (dgit 'diff)) (check-equal? (get-output-string diff-output) worktree-diff) (git 'add "sub/hello.txt") (check-equal? (git 'diff) "") (define cached-diff (git 'diff '--cached)) (check-true (regexp-match? #rx"-hello" cached-diff)) (check-true (regexp-match? #rx"[+]changed" cached-diff)) (git 'commit "prepare branches") (git 'checkout '-b "work") (call-with-output-file (build-path "sub" "hello.txt") #:exists 'truncate/replace (lambda (out) (displayln "work" out))) (git 'add) (git 'commit "work change") (check-equal? (file->string (build-path "sub" "hello.txt")) "work\n") (git 'checkout "master") (check-equal? (file->string (build-path "sub" "hello.txt")) "changed\n") (check-equal? (git-current-branch) "master") (check-not-false (member "work" (git 'branch))) ;; Safe checkout must not overwrite an uncommitted tracked change. (call-with-output-file (build-path "sub" "hello.txt") #:exists 'truncate/replace (lambda (out) (displayln "dirty" out))) (check-exn exn:fail? (lambda () (git 'checkout "work"))) (check-equal? (git-current-branch) "master") (check-equal? (file->string (build-path "sub" "hello.txt")) "dirty\n") (call-with-output-file (build-path "sub" "hello.txt") #:exists 'truncate/replace (lambda (out) (displayln "changed" out))) (git 'branch '-d "work") (check-false (member "work" (git 'branch))) (define tag-id (git 'tag "v0.1")) (check-equal? (string-length tag-id) 40) (check-equal? (git 'tag) '("v0.1")) (git 'checkout "v0.1") (check-false (git-current-branch)) (git 'checkout "master") (git 'tag '-d "v0.1") (check-equal? (git 'tag) '()) (check-equal? (length (git 'log 10)) 2))) (lambda () (delete-directory/files tmp)))