Simplifying.
This commit is contained in:
@@ -5,13 +5,19 @@ A small command-line-like Git module for Racket, implemented directly on top of
|
|||||||
```racket
|
```racket
|
||||||
(require git)
|
(require git)
|
||||||
|
|
||||||
(git status)
|
(git 'status)
|
||||||
(git add "main.rkt" "info.rkt")
|
(git 'add "main.rkt" "info.rkt")
|
||||||
(git commit "Implement raco support")
|
(git 'commit "Implement raco support")
|
||||||
(git tag "v0.2")
|
(git 'tag "v0.2")
|
||||||
(git checkout "main")
|
(git 'checkout "main")
|
||||||
|
|
||||||
|
;; Display-oriented variant:
|
||||||
|
(dgit 'status)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`git` is an ordinary procedure; command names are symbols. `dgit` performs the
|
||||||
|
same operation, displays a compact human-readable result, and returns that result.
|
||||||
|
|
||||||
The same operations are available as normal procedures such as `git-status`, `git-add`, `git-commit`, `git-tag`, and `git-checkout`.
|
The same operations are available as normal procedures such as `git-status`, `git-add`, `git-commit`, `git-tag`, and `git-checkout`.
|
||||||
|
|
||||||
## HTTPS credentials
|
## HTTPS credentials
|
||||||
@@ -24,13 +30,13 @@ PBKDF2-HMAC-SHA256.
|
|||||||
Create the credential store once:
|
Create the credential store once:
|
||||||
|
|
||||||
```racket
|
```racket
|
||||||
(git credentials init "store password")
|
(git 'credentials 'init "store password")
|
||||||
```
|
```
|
||||||
|
|
||||||
Store a token for a Git host:
|
Store a token for a Git host:
|
||||||
|
|
||||||
```racket
|
```racket
|
||||||
(git credentials set
|
(git 'credentials 'set
|
||||||
"https://git.dijkewijk.nl"
|
"https://git.dijkewijk.nl"
|
||||||
"hans"
|
"hans"
|
||||||
token)
|
token)
|
||||||
@@ -42,13 +48,13 @@ repositories on that host.
|
|||||||
The store is unlocked for one day by default:
|
The store is unlocked for one day by default:
|
||||||
|
|
||||||
```racket
|
```racket
|
||||||
(git credentials unlock "store password")
|
(git 'credentials 'unlock "store password")
|
||||||
```
|
```
|
||||||
|
|
||||||
or for an explicit number of seconds:
|
or for an explicit number of seconds:
|
||||||
|
|
||||||
```racket
|
```racket
|
||||||
(git credentials unlock "store password" (* 8 60 60))
|
(git 'credentials 'unlock "store password" (* 8 60 60))
|
||||||
```
|
```
|
||||||
|
|
||||||
The temporary unlock state is stored in `racket-git-unlock.ini` in Racket's
|
The temporary unlock state is stored in `racket-git-unlock.ini` in Racket's
|
||||||
@@ -61,16 +67,16 @@ so `racket-git-unlock.ini` must be treated as sensitive during that period.
|
|||||||
Lock immediately with:
|
Lock immediately with:
|
||||||
|
|
||||||
```racket
|
```racket
|
||||||
(git credentials lock)
|
(git 'credentials 'lock)
|
||||||
```
|
```
|
||||||
|
|
||||||
After credentials have been stored and the store is unlocked, normal remote
|
After credentials have been stored and the store is unlocked, normal remote
|
||||||
operations use them automatically:
|
operations use them automatically:
|
||||||
|
|
||||||
```racket
|
```racket
|
||||||
(git fetch)
|
(git 'fetch)
|
||||||
(git pull)
|
(git 'pull)
|
||||||
(git push)
|
(git 'push)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Supported Git operations
|
## Supported Git operations
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
(define collection "git")
|
(define collection "git")
|
||||||
(define pkg-desc "Command-line-like Git operations for Racket, implemented with libgit2")
|
(define pkg-desc "Command-line-like Git operations for Racket, implemented with libgit2")
|
||||||
(define version "0.2.1")
|
(define version "0.2.2")
|
||||||
(define pkg-authors '("Hans Dijkema"))
|
(define pkg-authors '("Hans Dijkema"))
|
||||||
(define license 'MIT)
|
(define license 'MIT)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
(require ffi/unsafe
|
(require ffi/unsafe
|
||||||
racket/list
|
racket/list
|
||||||
|
racket/match
|
||||||
racket/path
|
racket/path
|
||||||
racket/string
|
racket/string
|
||||||
"credentials.rkt"
|
"credentials.rkt"
|
||||||
@@ -11,6 +12,7 @@
|
|||||||
_git_error_code/check))
|
_git_error_code/check))
|
||||||
|
|
||||||
(provide git
|
(provide git
|
||||||
|
dgit
|
||||||
git-repository?
|
git-repository?
|
||||||
git-root
|
git-root
|
||||||
git-init
|
git-init
|
||||||
@@ -555,44 +557,93 @@
|
|||||||
remote-name
|
remote-name
|
||||||
(format "refs/tags/~a:refs/tags/~a" tag tag))]))
|
(format "refs/tags/~a:refs/tags/~a" tag tag))]))
|
||||||
|
|
||||||
(define-syntax git
|
(define (git command . args)
|
||||||
(syntax-rules (init clone status add config commit branch -d checkout -b
|
(unless (symbol? command)
|
||||||
tag log remote get-url fetch pull push push-tag
|
(raise-argument-error 'git "symbol?" command))
|
||||||
credentials init unlock lock set remove unlocked?)
|
(case command
|
||||||
[(_ init args ...) (git-init args ...)]
|
[(init) (apply git-init args)]
|
||||||
[(_ clone args ...) (git-clone args ...)]
|
[(clone) (apply git-clone args)]
|
||||||
[(_ status) (git-status)]
|
[(status) (apply git-status args)]
|
||||||
[(_ add paths ...) (git-add paths ...)]
|
[(add) (apply git-add args)]
|
||||||
[(_ config args ...) (git-config args ...)]
|
[(config) (apply git-config args)]
|
||||||
[(_ commit message) (git-commit message)]
|
[(commit) (apply git-commit args)]
|
||||||
[(_ branch -d name) (git-branch-delete name)]
|
[(branch)
|
||||||
[(_ branch) (git-branch)]
|
(match args
|
||||||
[(_ branch name) (git-branch name)]
|
[(list '-d name) (git-branch-delete name)]
|
||||||
[(_ checkout -b name) (git-checkout-new name)]
|
[_ (apply git-branch args)])]
|
||||||
[(_ checkout name) (git-checkout name)]
|
[(checkout)
|
||||||
[(_ tag -d name) (git-tag-delete name)]
|
(match args
|
||||||
[(_ tag) (git-tag)]
|
[(list '-b name) (git-checkout-new name)]
|
||||||
[(_ tag name) (git-tag name)]
|
[_ (apply git-checkout args)])]
|
||||||
[(_ log) (git-log)]
|
[(tag)
|
||||||
[(_ log count) (git-log count)]
|
(match args
|
||||||
[(_ remote) (git-remotes)]
|
[(list '-d name) (git-tag-delete name)]
|
||||||
[(_ remote add name url) (git-remote-add name url)]
|
[_ (apply git-tag args)])]
|
||||||
[(_ remote get-url name) (git-remote-url name)]
|
[(log) (apply git-log args)]
|
||||||
[(_ fetch) (git-fetch)]
|
[(remote)
|
||||||
[(_ fetch remote-name) (git-fetch remote-name)]
|
(match args
|
||||||
[(_ pull) (git-pull)]
|
['() (git-remotes)]
|
||||||
[(_ pull remote-name) (git-pull remote-name)]
|
[(list 'add name url) (git-remote-add name url)]
|
||||||
[(_ push) (git-push)]
|
[(list 'get-url name) (git-remote-url name)]
|
||||||
[(_ push remote-name) (git-push remote-name)]
|
[_ (error 'git "invalid remote arguments: ~e" args)])]
|
||||||
[(_ push remote-name branch) (git-push remote-name branch)]
|
[(fetch) (apply git-fetch args)]
|
||||||
[(_ push-tag tag-name) (git-push-tag tag-name)]
|
[(pull) (apply git-pull args)]
|
||||||
[(_ push-tag tag-name remote-name) (git-push-tag tag-name remote-name)]
|
[(push) (apply git-push args)]
|
||||||
[(_ credentials init password) (git-credentials-init! password)]
|
[(push-tag) (apply git-push-tag args)]
|
||||||
[(_ credentials unlock password) (git-credentials-unlock! password)]
|
[(credentials)
|
||||||
[(_ credentials unlock password seconds)
|
(match args
|
||||||
(git-credentials-unlock! password #:for seconds)]
|
[(list 'init password) (git-credentials-init! password)]
|
||||||
[(_ credentials lock) (git-credentials-lock!)]
|
[(list 'unlock password) (git-credentials-unlock! password)]
|
||||||
[(_ credentials unlocked?) (git-credentials-unlocked?)]
|
[(list 'unlock password seconds)
|
||||||
[(_ credentials set remote username token)
|
(git-credentials-unlock! password #:for seconds)]
|
||||||
(git-credentials-set! remote username token)]
|
[(list 'lock) (git-credentials-lock!)]
|
||||||
[(_ credentials remove remote) (git-credentials-remove! remote)]))
|
[(list 'unlocked?) (git-credentials-unlocked?)]
|
||||||
|
[(list 'set remote username token)
|
||||||
|
(git-credentials-set! remote username token)]
|
||||||
|
[(list 'remove remote) (git-credentials-remove! remote)]
|
||||||
|
[_ (error 'git "invalid credentials arguments: ~e" args)])]
|
||||||
|
[else (error 'git "unknown command: ~a" command)]))
|
||||||
|
|
||||||
|
(define (status-description entry)
|
||||||
|
(define flags (git-status-entry-flags entry))
|
||||||
|
(cond
|
||||||
|
[(has-status? flags 'GIT_STATUS_CONFLICTED) "Conflicted"]
|
||||||
|
[(has-status? flags 'GIT_STATUS_WT_NEW) "New"]
|
||||||
|
[(or (has-status? flags 'GIT_STATUS_INDEX_RENAMED)
|
||||||
|
(has-status? flags 'GIT_STATUS_WT_RENAMED)) "Renamed"]
|
||||||
|
[(or (has-status? flags 'GIT_STATUS_INDEX_DELETED)
|
||||||
|
(has-status? flags 'GIT_STATUS_WT_DELETED)) "Deleted"]
|
||||||
|
[(has-status? flags 'GIT_STATUS_INDEX_NEW) "Added"]
|
||||||
|
[(or (has-status? flags 'GIT_STATUS_INDEX_TYPECHANGE)
|
||||||
|
(has-status? flags 'GIT_STATUS_WT_TYPECHANGE)) "Type changed"]
|
||||||
|
[(or (has-status? flags 'GIT_STATUS_INDEX_MODIFIED)
|
||||||
|
(has-status? flags 'GIT_STATUS_WT_MODIFIED)) "Modified"]
|
||||||
|
[(has-status? flags 'GIT_STATUS_WT_UNREADABLE) "Unreadable"]
|
||||||
|
[else (git-status-entry-code entry)]))
|
||||||
|
|
||||||
|
(define (pad-right value width)
|
||||||
|
(define text (format "~a" value))
|
||||||
|
(string-append text (make-string (max 0 (- width (string-length text))) #\space)))
|
||||||
|
|
||||||
|
(define (display-git-result command result [out (current-output-port)])
|
||||||
|
(cond
|
||||||
|
[(eq? command 'status)
|
||||||
|
(for ([entry (in-list result)])
|
||||||
|
(fprintf out "~a - ~a\n"
|
||||||
|
(pad-right (status-description entry) 12)
|
||||||
|
(git-status-entry-path entry)))]
|
||||||
|
[(eq? command 'log)
|
||||||
|
(for ([entry (in-list result)])
|
||||||
|
(fprintf out "~a ~a\n"
|
||||||
|
(substring (git-log-entry-id entry) 0 7)
|
||||||
|
(git-log-entry-summary entry)))]
|
||||||
|
[(list? result)
|
||||||
|
(for ([item (in-list result)])
|
||||||
|
(displayln item out))]
|
||||||
|
[(void? result) (void)]
|
||||||
|
[else (displayln result out)]))
|
||||||
|
|
||||||
|
(define (dgit command . args)
|
||||||
|
(define result (apply git command args))
|
||||||
|
(display-git-result command result)
|
||||||
|
result)
|
||||||
|
|||||||
+37
-29
@@ -14,17 +14,25 @@ The short form is intended for build scripts and interactive use:
|
|||||||
@racketblock[
|
@racketblock[
|
||||||
(require git)
|
(require git)
|
||||||
|
|
||||||
(git status)
|
(git 'status)
|
||||||
(git add "main.rkt" "info.rkt")
|
(git 'add "main.rkt" "info.rkt")
|
||||||
(git commit "Implement raco support")
|
(git 'commit "Implement raco support")
|
||||||
(git tag "v0.1")
|
(git 'tag "v0.1")
|
||||||
(git checkout "main")
|
(git 'checkout "main")
|
||||||
]
|
]
|
||||||
|
|
||||||
@defform[(git command argument ...)]{
|
@defproc[(git [command symbol?] [argument any/c] ...) any/c]{
|
||||||
The @racket[git] form is syntax sugar for the corresponding procedures. For example, @racket[(git status)] calls @racket[git-status], and @racket[(git commit "message")] calls @racket[git-commit].
|
Dispatches @racket[command] to the corresponding Git procedure. For example, @racket[(git 'status)] calls @racket[git-status], and @racket[(git 'commit "message")] calls @racket[git-commit]. Command names are ordinary symbols, so @racket[git] can safely be used inside other macros and DSLs.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@defproc[(dgit [command symbol?] [argument any/c] ...) any/c]{
|
||||||
|
Calls @racket[git], displays its result in a compact human-readable form, and returns the original result. Status entries are displayed with labels such as @tt{Modified}, @tt{New}, @tt{Deleted}, and @tt{Renamed}. Ignored files remain omitted, just as with @racket[git-status].
|
||||||
|
}
|
||||||
|
|
||||||
|
@racketblock[
|
||||||
|
(dgit 'status)
|
||||||
|
]
|
||||||
|
|
||||||
@section{Repository}
|
@section{Repository}
|
||||||
|
|
||||||
@defproc[(git-repository? [path path-string? (current-directory)]) boolean?]{Returns whether @racket[path] is inside a Git repository.}
|
@defproc[(git-repository? [path path-string? (current-directory)]) boolean?]{Returns whether @racket[path] is inside a Git repository.}
|
||||||
@@ -108,28 +116,28 @@ Remote HTTPS operations automatically use credentials from the @tt{racket-git} c
|
|||||||
The following command-like forms are supported directly:
|
The following command-like forms are supported directly:
|
||||||
|
|
||||||
@racketblock[
|
@racketblock[
|
||||||
(git init)
|
(git 'init)
|
||||||
(git clone "https://example/repo.git")
|
(git 'clone "https://example/repo.git")
|
||||||
(git status)
|
(git 'status)
|
||||||
(git add "file.rkt")
|
(git 'add "file.rkt")
|
||||||
(git config "user.name" "Name")
|
(git 'config "user.name" "Name")
|
||||||
(git commit "message")
|
(git 'commit "message")
|
||||||
(git branch)
|
(git 'branch)
|
||||||
(git branch "feature")
|
(git 'branch "feature")
|
||||||
(git branch -d "feature")
|
(git 'branch '-d "feature")
|
||||||
(git checkout "main")
|
(git 'checkout "main")
|
||||||
(git checkout -b "feature")
|
(git 'checkout '-b "feature")
|
||||||
(git tag)
|
(git 'tag)
|
||||||
(git tag "v0.1")
|
(git 'tag "v0.1")
|
||||||
(git tag -d "v0.1")
|
(git 'tag '-d "v0.1")
|
||||||
(git log 10)
|
(git 'log 10)
|
||||||
(git remote)
|
(git 'remote)
|
||||||
(git remote add "origin" "https://example/repo.git")
|
(git 'remote 'add "origin" "https://example/repo.git")
|
||||||
(git remote get-url "origin")
|
(git 'remote 'get-url "origin")
|
||||||
(git fetch)
|
(git 'fetch)
|
||||||
(git pull)
|
(git 'pull)
|
||||||
(git push)
|
(git 'push)
|
||||||
(git push-tag "v0.1")
|
(git 'push-tag "v0.1")
|
||||||
]
|
]
|
||||||
|
|
||||||
@section{HTTPS credentials}
|
@section{HTTPS credentials}
|
||||||
|
|||||||
+29
-19
@@ -11,13 +11,13 @@
|
|||||||
(lambda ()
|
(lambda ()
|
||||||
(make-directory (build-path tmp "sub"))
|
(make-directory (build-path tmp "sub"))
|
||||||
(parameterize ([current-directory tmp])
|
(parameterize ([current-directory tmp])
|
||||||
(git init)
|
(git 'init)
|
||||||
(check-true (git-repository?))
|
(check-true (git-repository?))
|
||||||
(check-equal? (git-current-branch) "master")
|
(check-equal? (git-current-branch) "master")
|
||||||
(check-true (git-clean?))
|
(check-true (git-clean?))
|
||||||
|
|
||||||
(git config "user.name" "Racket Git Test")
|
(git 'config "user.name" "Racket Git Test")
|
||||||
(git config "user.email" "racket-git-test@example.invalid")
|
(git 'config "user.email" "racket-git-test@example.invalid")
|
||||||
(check-equal? (git-config "user.name") "Racket Git Test")
|
(check-equal? (git-config "user.name") "Racket Git Test")
|
||||||
|
|
||||||
(call-with-output-file ".gitignore"
|
(call-with-output-file ".gitignore"
|
||||||
@@ -33,41 +33,51 @@
|
|||||||
(check-equal? (git-status-lines)
|
(check-equal? (git-status-lines)
|
||||||
'("?? .gitignore" "?? sub/hello.txt"))
|
'("?? .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")])
|
(parameterize ([current-directory (build-path tmp "sub")])
|
||||||
(git add "hello.txt"))
|
(git 'add "hello.txt"))
|
||||||
(check-equal? (git-status-lines)
|
(check-equal? (git-status-lines)
|
||||||
'("?? .gitignore" "A sub/hello.txt"))
|
'("?? .gitignore" "A sub/hello.txt"))
|
||||||
|
|
||||||
(git add ".gitignore")
|
(git 'add ".gitignore")
|
||||||
(define first (git-commit "initial commit"))
|
(define first (git-commit "initial commit"))
|
||||||
(check-equal? (string-length first) 40)
|
(check-equal? (string-length first) 40)
|
||||||
(check-true (git-clean?))
|
(check-true (git-clean?))
|
||||||
|
|
||||||
(git checkout -b "work")
|
(git 'checkout '-b "work")
|
||||||
(call-with-output-file (build-path "sub" "hello.txt")
|
(call-with-output-file (build-path "sub" "hello.txt")
|
||||||
#:exists 'truncate/replace
|
#:exists 'truncate/replace
|
||||||
(lambda (out) (displayln "work" out)))
|
(lambda (out) (displayln "work" out)))
|
||||||
(git add)
|
(git 'add)
|
||||||
(git commit "work change")
|
(git 'commit "work change")
|
||||||
(check-equal? (file->string (build-path "sub" "hello.txt")) "work\n")
|
(check-equal? (file->string (build-path "sub" "hello.txt")) "work\n")
|
||||||
|
|
||||||
(git checkout "master")
|
(git 'checkout "master")
|
||||||
(check-equal? (file->string (build-path "sub" "hello.txt")) "hello\n")
|
(check-equal? (file->string (build-path "sub" "hello.txt")) "hello\n")
|
||||||
(check-equal? (git-current-branch) "master")
|
(check-equal? (git-current-branch) "master")
|
||||||
(check-not-false (member "work" (git branch)))
|
(check-not-false (member "work" (git 'branch)))
|
||||||
|
|
||||||
(git branch -d "work")
|
(git 'branch '-d "work")
|
||||||
(check-false (member "work" (git branch)))
|
(check-false (member "work" (git 'branch)))
|
||||||
|
|
||||||
(define tag-id (git tag "v0.1"))
|
(define tag-id (git 'tag "v0.1"))
|
||||||
(check-equal? (string-length tag-id) 40)
|
(check-equal? (string-length tag-id) 40)
|
||||||
(check-equal? (git tag) '("v0.1"))
|
(check-equal? (git 'tag) '("v0.1"))
|
||||||
(git checkout "v0.1")
|
(git 'checkout "v0.1")
|
||||||
(check-false (git-current-branch))
|
(check-false (git-current-branch))
|
||||||
(git checkout "master")
|
(git 'checkout "master")
|
||||||
(git tag -d "v0.1")
|
(git 'tag '-d "v0.1")
|
||||||
(check-equal? (git tag) '())
|
(check-equal? (git 'tag) '())
|
||||||
|
|
||||||
(check-equal? (length (git log 10)) 1)))
|
(check-equal? (length (git 'log 10)) 1)))
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(delete-directory/files tmp)))
|
(delete-directory/files tmp)))
|
||||||
|
|||||||
+23
-23
@@ -10,8 +10,8 @@
|
|||||||
(define b (build-path tmp "b"))
|
(define b (build-path tmp "b"))
|
||||||
|
|
||||||
(define (configure!)
|
(define (configure!)
|
||||||
(git config "user.name" "Racket Git Test")
|
(git 'config "user.name" "Racket Git Test")
|
||||||
(git config "user.email" "racket-git-test@example.invalid"))
|
(git 'config "user.email" "racket-git-test@example.invalid"))
|
||||||
|
|
||||||
(dynamic-wind
|
(dynamic-wind
|
||||||
void
|
void
|
||||||
@@ -20,17 +20,17 @@
|
|||||||
(make-directory a)
|
(make-directory a)
|
||||||
|
|
||||||
(parameterize ([current-directory a])
|
(parameterize ([current-directory a])
|
||||||
(git init)
|
(git 'init)
|
||||||
(configure!)
|
(configure!)
|
||||||
(call-with-output-file "value.txt"
|
(call-with-output-file "value.txt"
|
||||||
#:exists 'truncate/replace
|
#:exists 'truncate/replace
|
||||||
(lambda (out) (displayln "one" out)))
|
(lambda (out) (displayln "one" out)))
|
||||||
(git add "value.txt")
|
(git 'add "value.txt")
|
||||||
(git commit "one")
|
(git 'commit "one")
|
||||||
(git remote add "origin" (path->string origin))
|
(git 'remote 'add "origin" (path->string origin))
|
||||||
(check-equal? (git remote) '("origin"))
|
(check-equal? (git 'remote) '("origin"))
|
||||||
(check-equal? (git remote get-url "origin") (path->string origin))
|
(check-equal? (git 'remote 'get-url "origin") (path->string origin))
|
||||||
(git push))
|
(git 'push))
|
||||||
|
|
||||||
(git-clone (path->string origin) b)
|
(git-clone (path->string origin) b)
|
||||||
(parameterize ([current-directory b])
|
(parameterize ([current-directory b])
|
||||||
@@ -39,38 +39,38 @@
|
|||||||
(call-with-output-file "value.txt"
|
(call-with-output-file "value.txt"
|
||||||
#:exists 'truncate/replace
|
#:exists 'truncate/replace
|
||||||
(lambda (out) (displayln "two" out)))
|
(lambda (out) (displayln "two" out)))
|
||||||
(git add "value.txt")
|
(git 'add "value.txt")
|
||||||
(git commit "two")
|
(git 'commit "two")
|
||||||
(git push)
|
(git 'push)
|
||||||
(git tag "v2")
|
(git 'tag "v2")
|
||||||
(git push-tag "v2"))
|
(git 'push-tag "v2"))
|
||||||
|
|
||||||
(parameterize ([current-directory a])
|
(parameterize ([current-directory a])
|
||||||
(check-equal? (file->string "value.txt") "one\n")
|
(check-equal? (file->string "value.txt") "one\n")
|
||||||
(check-equal? (string-length (git pull)) 40)
|
(check-equal? (string-length (git 'pull)) 40)
|
||||||
(check-equal? (file->string "value.txt") "two\n")
|
(check-equal? (file->string "value.txt") "two\n")
|
||||||
(check-true (git-clean?))
|
(check-true (git-clean?))
|
||||||
(git fetch)
|
(git 'fetch)
|
||||||
(check-equal? (git tag) '("v2"))
|
(check-equal? (git 'tag) '("v2"))
|
||||||
|
|
||||||
(call-with-output-file "local.txt"
|
(call-with-output-file "local.txt"
|
||||||
#:exists 'truncate/replace
|
#:exists 'truncate/replace
|
||||||
(lambda (out) (displayln "local" out)))
|
(lambda (out) (displayln "local" out)))
|
||||||
(git add "local.txt")
|
(git 'add "local.txt")
|
||||||
(git commit "local change"))
|
(git 'commit "local change"))
|
||||||
|
|
||||||
(parameterize ([current-directory b])
|
(parameterize ([current-directory b])
|
||||||
(call-with-output-file "remote.txt"
|
(call-with-output-file "remote.txt"
|
||||||
#:exists 'truncate/replace
|
#:exists 'truncate/replace
|
||||||
(lambda (out) (displayln "remote" out)))
|
(lambda (out) (displayln "remote" out)))
|
||||||
(git add "remote.txt")
|
(git 'add "remote.txt")
|
||||||
(git commit "remote change")
|
(git 'commit "remote change")
|
||||||
(git push))
|
(git 'push))
|
||||||
|
|
||||||
(parameterize ([current-directory a])
|
(parameterize ([current-directory a])
|
||||||
(define before (git-head))
|
(define before (git-head))
|
||||||
(check-exn #rx"non-fast-forward"
|
(check-exn #rx"non-fast-forward"
|
||||||
(lambda () (git pull)))
|
(lambda () (git 'pull)))
|
||||||
(check-equal? (git-head) before)
|
(check-equal? (git-head) before)
|
||||||
(check-true (file-exists? "local.txt"))
|
(check-true (file-exists? "local.txt"))
|
||||||
(check-false (file-exists? "remote.txt"))))
|
(check-false (file-exists? "remote.txt"))))
|
||||||
|
|||||||
Reference in New Issue
Block a user