Change time-related flags to durations

Add '--period' to replace '--wait', which is now obsolete.

Add '--sync-timeout' to replace '--timeout', which is now obsolete.

Both of these new flags take a Go-style time string, rather than a bare
number. For example "1s" for 1 second or "1m" for one minute.

The old flags have been kept and will take precedence if specified.
This commit is contained in:
Tim Hockin 2020-10-31 00:31:53 -07:00
parent b0eebbc7ad
commit fa0e8696e2
4 changed files with 72 additions and 55 deletions

View File

@ -48,7 +48,7 @@ docker run -d \
registry/git-sync:tag \ registry/git-sync:tag \
--repo=https://github.com/kubernetes/git-sync \ --repo=https://github.com/kubernetes/git-sync \
--branch=master \ --branch=master \
--wait=30 --period=30s
# run an nginx container to serve the content # run an nginx container to serve the content
docker run -d \ docker run -d \
@ -74,7 +74,7 @@ docker run -d \
registry/git-sync:tag \ registry/git-sync:tag \
--repo=https://github.com/kubernetes/git-sync \ --repo=https://github.com/kubernetes/git-sync \
--branch=master \ --branch=master \
--wait=30 \ --period=30s \
--webhook-url="http://localhost:9090/-/reload" --webhook-url="http://localhost:9090/-/reload"
``` ```
@ -89,8 +89,8 @@ docker run -d \
| GIT_SYNC_SUBMODULES | `--submodules` | git submodule behavior: one of 'recursive', 'shallow', or 'off' | recursive | | GIT_SYNC_SUBMODULES | `--submodules` | git submodule behavior: one of 'recursive', 'shallow', or 'off' | recursive |
| GIT_SYNC_ROOT | `--root` | the root directory for git-sync operations, under which --dest will be created | "$HOME/git" | | GIT_SYNC_ROOT | `--root` | the root directory for git-sync operations, under which --dest will be created | "$HOME/git" |
| GIT_SYNC_DEST | `--dest` | the name of (a symlink to) a directory in which to check-out files under --root (defaults to the leaf dir of --repo) | "" | | GIT_SYNC_DEST | `--dest` | the name of (a symlink to) a directory in which to check-out files under --root (defaults to the leaf dir of --repo) | "" |
| GIT_SYNC_WAIT | `--wait` | the number of seconds between syncs | 1 (second) | | GIT_SYNC_PERIOD | `--period` | how long to wait between syncs, must be >= 10ms | "10s" |
| GIT_SYNC_TIMEOUT | `--timeout` | the max number of seconds allowed for a complete sync | 120 | | GIT_SYNC_SYNC_TIMEOUT | `--sync-timeout` | the total time allowed for one complete sync, must be >= 10ms | "120s" |
| GIT_SYNC_ONE_TIME | `--one-time` | exit after the first sync | false | | GIT_SYNC_ONE_TIME | `--one-time` | exit after the first sync | false |
| GIT_SYNC_MAX_SYNC_FAILURES | `--max-sync-failures` | the number of consecutive failures allowed before aborting (the first sync must succeed, -1 will retry forever after the initial sync) | 0 | | GIT_SYNC_MAX_SYNC_FAILURES | `--max-sync-failures` | the number of consecutive failures allowed before aborting (the first sync must succeed, -1 will retry forever after the initial sync) | 0 |
| GIT_SYNC_PERMISSIONS | `--change-permissions` | the file permissions to apply to the checked-out files (0 will not change permissions at all) | 0 | | GIT_SYNC_PERMISSIONS | `--change-permissions` | the file permissions to apply to the checked-out files (0 will not change permissions at all) | 0 |

View File

@ -66,10 +66,10 @@ var flRoot = pflag.String("root", envString("GIT_SYNC_ROOT", envString("HOME", "
"the root directory for git-sync operations, under which --dest will be created") "the root directory for git-sync operations, under which --dest will be created")
var flDest = pflag.String("dest", envString("GIT_SYNC_DEST", ""), var flDest = pflag.String("dest", envString("GIT_SYNC_DEST", ""),
"the name of (a symlink to) a directory in which to check-out files under --root (defaults to the leaf dir of --repo)") "the name of (a symlink to) a directory in which to check-out files under --root (defaults to the leaf dir of --repo)")
var flWait = pflag.Float64("wait", envFloat("GIT_SYNC_WAIT", 1), var flPeriod = pflag.Duration("period", envDuration("GIT_SYNC_PERIOD", 10*time.Second),
"the number of seconds between syncs") "how long to wait between syncs, must be >= 10ms; --wait overrides this")
var flSyncTimeout = pflag.Int("timeout", envInt("GIT_SYNC_TIMEOUT", 120), var flSyncTimeout = pflag.Duration("sync-timeout", envDuration("GIT_SYNC_SYNC_TIMEOUT", 120*time.Second),
"the number of seconds allowed for a complete sync") "the total time allowed for one complete sync, must be >= 10ms; --timeout overrides this")
var flOneTime = pflag.Bool("one-time", envBool("GIT_SYNC_ONE_TIME", false), var flOneTime = pflag.Bool("one-time", envBool("GIT_SYNC_ONE_TIME", false),
"exit after the first sync") "exit after the first sync")
var flMaxSyncFailures = pflag.Int("max-sync-failures", envInt("GIT_SYNC_MAX_SYNC_FAILURES", 0), var flMaxSyncFailures = pflag.Int("max-sync-failures", envInt("GIT_SYNC_MAX_SYNC_FAILURES", 0),
@ -123,6 +123,17 @@ var flHTTPMetrics = pflag.Bool("http-metrics", envBool("GIT_SYNC_HTTP_METRICS",
var flHTTPprof = pflag.Bool("http-pprof", envBool("GIT_SYNC_HTTP_PPROF", false), var flHTTPprof = pflag.Bool("http-pprof", envBool("GIT_SYNC_HTTP_PPROF", false),
"enable the pprof debug endpoints on git-sync's HTTP endpoint") "enable the pprof debug endpoints on git-sync's HTTP endpoint")
// Obsolete flags, kept for compat.
var flWait = pflag.Float64("wait", envFloat("GIT_SYNC_WAIT", 0),
"DEPRECATED: use --period instead")
var flTimeout = pflag.Int("timeout", envInt("GIT_SYNC_TIMEOUT", 0),
"DEPRECATED: use --sync-timeout instead")
func init() {
pflag.CommandLine.MarkDeprecated("wait", "use --period instead")
pflag.CommandLine.MarkDeprecated("timeout", "use --sync-timeout instead")
}
var log = glogr.New() var log = glogr.New()
// Total pull/error, summary on pull duration // Total pull/error, summary on pull duration
@ -150,9 +161,6 @@ const (
metricKeyNoOp = "noop" metricKeyNoOp = "noop"
) )
// initTimeout is a timeout for initialization, like git credentials setup.
const initTimeout = time.Second * 30
const ( const (
submodulesRecursive = "recursive" submodulesRecursive = "recursive"
submodulesShallow = "shallow" submodulesShallow = "shallow"
@ -308,14 +316,20 @@ func main() {
os.Exit(1) os.Exit(1)
} }
if *flWait < 0 { if *flWait != 0 {
fmt.Fprintf(os.Stderr, "ERROR: --wait must be greater than or equal to 0\n") *flPeriod = time.Duration(int(*flWait*1000)) * time.Millisecond
}
if *flPeriod < 10*time.Millisecond {
fmt.Fprintf(os.Stderr, "ERROR: --period must be at least 10ms\n")
pflag.Usage() pflag.Usage()
os.Exit(1) os.Exit(1)
} }
if *flSyncTimeout < 0 { if *flTimeout != 0 {
fmt.Fprintf(os.Stderr, "ERROR: --timeout must be greater than 0\n") *flSyncTimeout = time.Duration(*flTimeout) * time.Second
}
if *flSyncTimeout < 10*time.Millisecond {
fmt.Fprintf(os.Stderr, "ERROR: --sync-timeout must be at least 10ms\n")
pflag.Usage() pflag.Usage()
os.Exit(1) os.Exit(1)
} }
@ -382,8 +396,8 @@ func main() {
} }
// This context is used only for git credentials initialization. There are no long-running operations like // This context is used only for git credentials initialization. There are no long-running operations like
// `git clone`, so initTimeout set to 30 seconds should be enough. // `git clone`, so hopefully 30 seconds will be enough.
ctx, cancel := context.WithTimeout(context.Background(), initTimeout) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
if *flUsername != "" && *flPassword != "" { if *flUsername != "" && *flPassword != "" {
if err := setupGitAuth(ctx, *flUsername, *flPassword, *flRepo); err != nil { if err := setupGitAuth(ctx, *flUsername, *flPassword, *flRepo); err != nil {
@ -471,7 +485,7 @@ func main() {
failCount := 0 failCount := 0
for { for {
start := time.Now() start := time.Now()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(*flSyncTimeout)) ctx, cancel := context.WithTimeout(context.Background(), *flSyncTimeout)
if changed, hash, err := syncRepo(ctx, *flRepo, *flBranch, *flRev, *flDepth, *flRoot, *flDest, *flAskPassURL, *flSubmodules); err != nil { if changed, hash, err := syncRepo(ctx, *flRepo, *flBranch, *flRev, *flDepth, *flRoot, *flDest, *flAskPassURL, *flSubmodules); err != nil {
updateSyncMetrics(metricKeyError, start) updateSyncMetrics(metricKeyError, start)
if *flMaxSyncFailures != -1 && failCount >= *flMaxSyncFailures { if *flMaxSyncFailures != -1 && failCount >= *flMaxSyncFailures {
@ -482,9 +496,9 @@ func main() {
failCount++ failCount++
log.Error(err, "unexpected error syncing repo, will retry") log.Error(err, "unexpected error syncing repo, will retry")
log.V(0).Info("waiting before retrying", "waitTime", waitTime(*flWait)) log.V(0).Info("waiting before retrying", "waitTime", flPeriod.String())
cancel() cancel()
time.Sleep(waitTime(*flWait)) time.Sleep(*flPeriod)
continue continue
} else if changed { } else if changed {
if webhook != nil { if webhook != nil {
@ -510,9 +524,9 @@ func main() {
} }
failCount = 0 failCount = 0
log.V(1).Info("next sync", "wait_time", waitTime(*flWait)) log.V(1).Info("next sync", "waitTime", flPeriod.String())
cancel() cancel()
time.Sleep(waitTime(*flWait)) time.Sleep(*flPeriod)
} }
} }
@ -521,10 +535,6 @@ func updateSyncMetrics(key string, start time.Time) {
syncCount.WithLabelValues(key).Inc() syncCount.WithLabelValues(key).Inc()
} }
func waitTime(seconds float64) time.Duration {
return time.Duration(int(seconds*1000)) * time.Millisecond
}
// Do no work, but don't do something that triggers go's runtime into thinking // Do no work, but don't do something that triggers go's runtime into thinking
// it is deadlocked. // it is deadlocked.
func sleepForever() { func sleepForever() {
@ -1113,6 +1123,11 @@ OPTIONS
users should prefer the environment variable for specifying the users should prefer the environment variable for specifying the
password. password.
--period <duration>, $GIT_SYNC_PERIOD
How long to wait between sync attempts. This must be at least
10ms. This flag obsoletes --wait, but if --wait is specifed, it
will take precedence. (default: 10s)
--repo <string>, $GIT_SYNC_REPO --repo <string>, $GIT_SYNC_REPO
The git repository to sync. The git repository to sync.
@ -1145,11 +1160,13 @@ OPTIONS
An optional command to be executed after syncing a new hash of the An optional command to be executed after syncing a new hash of the
remote repository. This command does not take any arguments and remote repository. This command does not take any arguments and
executes with the synced repo as its working directory. The executes with the synced repo as its working directory. The
execution is subject to the overall --timeout flag and will extend execution is subject to the overall --sync-timeout flag and will
the period between syncs attempts. extend the effective period between sync attempts.
--timeout <int>, $GIT_SYNC_TIMEOUT --sync-timeout <duration>, $GIT_SYNC_SYNC_TIMEOUT
The number of seconds allowed for a complete sync. (default: 120) The total time allowed for one complete sync. This must be at least
10ms. This flag obsoletes --timeout, but if --timeout is specified,
it will take precedence. (default: 120s)
--username <string>, $GIT_SYNC_USERNAME --username <string>, $GIT_SYNC_USERNAME
The username to use for git authentication (see --password). The username to use for git authentication (see --password).
@ -1161,9 +1178,6 @@ OPTIONS
--version --version
Print the version and exit. Print the version and exit.
--wait <float>, $GIT_SYNC_WAIT
The number of seconds between sync attempts. (default: 1)
--webhook-backoff <duration>, $GIT_SYNC_WEBHOOK_BACKOFF --webhook-backoff <duration>, $GIT_SYNC_WEBHOOK_BACKOFF
The time to wait before retrying a failed --webhook-url). The time to wait before retrying a failed --webhook-url).
(default: 3s) (default: 3s)
@ -1188,7 +1202,7 @@ EXAMPLE USAGE
--repo=https://github.com/kubernetes/git-sync \ --repo=https://github.com/kubernetes/git-sync \
--branch=master \ --branch=master \
--rev=HEAD \ --rev=HEAD \
--wait=10 \ --period=10s \
--root=/mnt/git --root=/mnt/git
AUTHENTICATION AUTHENTICATION

View File

@ -81,7 +81,7 @@ func (w *Webhook) Do(hash string) error {
defer cancel() defer cancel()
req = req.WithContext(ctx) req = req.WithContext(ctx)
log.V(0).Info("sending webhook", "hash", hash, "url", w.URL, "method", w.Method, "timeout", w.Timeout) log.V(0).Info("sending webhook", "hash", hash, "url", w.URL, "method", w.Method, "timeout", w.Timeout.String())
resp, err := http.DefaultClient.Do(req) resp, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {
return err return err
@ -113,7 +113,7 @@ func (w *Webhook) run() {
} }
if err := w.Do(hash); err != nil { if err := w.Do(hash); err != nil {
log.Error(err, "webhook failed", "url", w.URL, "method", w.Method, "timeout", w.Timeout) log.Error(err, "webhook failed", "url", w.URL, "method", w.Method, "timeout", w.Timeout.String())
time.Sleep(w.Backoff) time.Sleep(w.Backoff)
} else { } else {
lastHash = hash lastHash = hash

View File

@ -172,7 +172,7 @@ testcase "default-sync"
echo "$TESTCASE 1" > "$REPO"/file echo "$TESTCASE 1" > "$REPO"/file
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
GIT_SYNC \ GIT_SYNC \
--wait=0.1 \ --period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--root="$ROOT" \ --root="$ROOT" \
--dest="link" \ --dest="link" \
@ -205,7 +205,7 @@ testcase "head-sync"
echo "$TESTCASE 1" > "$REPO"/file echo "$TESTCASE 1" > "$REPO"/file
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
GIT_SYNC \ GIT_SYNC \
--wait=0.1 \ --period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--branch=master \ --branch=master \
--rev=HEAD \ --rev=HEAD \
@ -243,7 +243,7 @@ echo "$TESTCASE 1" > "$REPO"/file
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
git -C "$REPO" checkout -q master git -C "$REPO" checkout -q master
GIT_SYNC \ GIT_SYNC \
--wait=0.1 \ --period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--branch="$BRANCH" \ --branch="$BRANCH" \
--root="$ROOT" \ --root="$ROOT" \
@ -283,7 +283,7 @@ echo "$TESTCASE 1" > "$REPO"/file
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
git -C "$REPO" tag -f "$TAG" >/dev/null git -C "$REPO" tag -f "$TAG" >/dev/null
GIT_SYNC \ GIT_SYNC \
--wait=0.1 \ --period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--rev="$TAG" \ --rev="$TAG" \
--root="$ROOT" \ --root="$ROOT" \
@ -328,7 +328,7 @@ echo "$TESTCASE 1" > "$REPO"/file
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
git -C "$REPO" tag -af "$TAG" -m "$TESTCASE 1" >/dev/null git -C "$REPO" tag -af "$TAG" -m "$TESTCASE 1" >/dev/null
GIT_SYNC \ GIT_SYNC \
--wait=0.1 \ --period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--rev="$TAG" \ --rev="$TAG" \
--root="$ROOT" \ --root="$ROOT" \
@ -372,7 +372,7 @@ echo "$TESTCASE 1" > "$REPO"/file
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
REV=$(git -C "$REPO" rev-list -n1 HEAD) REV=$(git -C "$REPO" rev-list -n1 HEAD)
GIT_SYNC \ GIT_SYNC \
--wait=0.1 \ --period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--rev="$REV" \ --rev="$REV" \
--root="$ROOT" \ --root="$ROOT" \
@ -460,7 +460,7 @@ git -C "$REPO" commit -qam "$TESTCASE 1"
GIT_SYNC \ GIT_SYNC \
--git="$SLOW_GIT" \ --git="$SLOW_GIT" \
--one-time \ --one-time \
--timeout=1 \ --sync-timeout=1s \
--repo="file://$REPO" \ --repo="file://$REPO" \
--root="$ROOT" \ --root="$ROOT" \
--dest="link" \ --dest="link" \
@ -470,8 +470,8 @@ assert_file_absent "$ROOT"/link/file
# run with slow_git but without timing out # run with slow_git but without timing out
GIT_SYNC \ GIT_SYNC \
--git="$SLOW_GIT" \ --git="$SLOW_GIT" \
--wait=0.1 \ --period=100ms \
--timeout=16 \ --sync-timeout=16s \
--repo="file://$REPO" \ --repo="file://$REPO" \
--root="$ROOT" \ --root="$ROOT" \
--dest="link" \ --dest="link" \
@ -499,7 +499,7 @@ echo "$TESTCASE 1" > "$REPO"/file
expected_depth="1" expected_depth="1"
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
GIT_SYNC \ GIT_SYNC \
--wait=0.1 \ --period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--depth="$expected_depth" \ --depth="$expected_depth" \
--root="$ROOT" \ --root="$ROOT" \
@ -634,7 +634,7 @@ testcase "sync_hook_command"
echo "$TESTCASE 1" > "$REPO"/file echo "$TESTCASE 1" > "$REPO"/file
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
GIT_SYNC \ GIT_SYNC \
--wait=0.1 \ --period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--root="$ROOT" \ --root="$ROOT" \
--dest="link" \ --dest="link" \
@ -667,6 +667,7 @@ freencport
echo "$TESTCASE 1" > "$REPO"/file echo "$TESTCASE 1" > "$REPO"/file
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
GIT_SYNC \ GIT_SYNC \
--period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--root="$ROOT" \ --root="$ROOT" \
--webhook-url="http://127.0.0.1:$NCPORT" \ --webhook-url="http://127.0.0.1:$NCPORT" \
@ -709,6 +710,7 @@ freencport
echo "$TESTCASE 1" > "$REPO"/file echo "$TESTCASE 1" > "$REPO"/file
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
GIT_SYNC \ GIT_SYNC \
--period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--root="$ROOT" \ --root="$ROOT" \
--webhook-url="http://127.0.0.1:$NCPORT" \ --webhook-url="http://127.0.0.1:$NCPORT" \
@ -735,6 +737,7 @@ echo "$TESTCASE 1" > "$REPO"/file
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
GIT_SYNC \ GIT_SYNC \
--git="$SLOW_GIT" \ --git="$SLOW_GIT" \
--period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--root="$ROOT" \ --root="$ROOT" \
--http-bind=":$BINDPORT" \ --http-bind=":$BINDPORT" \
@ -795,7 +798,7 @@ git -C "$NESTED_SUBMODULE" commit -aqm "init nested-submodule file"
git -C "$REPO" submodule add -q file://$SUBMODULE git -C "$REPO" submodule add -q file://$SUBMODULE
git -C "$REPO" commit -aqm "add submodule" git -C "$REPO" commit -aqm "add submodule"
GIT_SYNC \ GIT_SYNC \
--wait=0.1 \ --period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--root="$ROOT" \ --root="$ROOT" \
--dest="link" \ --dest="link" \
@ -882,7 +885,7 @@ git -C "$REPO" submodule add -q file://$SUBMODULE
git -C "$REPO" config -f "$REPO"/.gitmodules submodule.$SUBMODULE_REPO_NAME.shallow true git -C "$REPO" config -f "$REPO"/.gitmodules submodule.$SUBMODULE_REPO_NAME.shallow true
git -C "$REPO" commit -qam "$TESTCASE 1" git -C "$REPO" commit -qam "$TESTCASE 1"
GIT_SYNC \ GIT_SYNC \
--wait=0.1 \ --period=100ms \
--repo="file://$REPO" \ --repo="file://$REPO" \
--depth="$expected_depth" \ --depth="$expected_depth" \
--root="$ROOT" \ --root="$ROOT" \
@ -957,11 +960,11 @@ git -C "$REPO" submodule add -q file://$SUBMODULE
git -C "$REPO" commit -aqm "add submodule" git -C "$REPO" commit -aqm "add submodule"
GIT_SYNC \ GIT_SYNC \
--submodules=off \ --period=100ms \
--wait=0.1 \
--repo="file://$REPO" \ --repo="file://$REPO" \
--root="$ROOT" \ --root="$ROOT" \
--dest="link" \ --dest="link" \
--submodules=off \
> "$DIR"/log."$TESTCASE" 2>&1 & > "$DIR"/log."$TESTCASE" 2>&1 &
sleep 3 sleep 3
assert_file_absent "$ROOT"/link/$SUBMODULE_REPO_NAME/submodule assert_file_absent "$ROOT"/link/$SUBMODULE_REPO_NAME/submodule
@ -999,11 +1002,11 @@ git -C "$REPO" submodule add -q file://$SUBMODULE
git -C "$REPO" commit -aqm "add submodule" git -C "$REPO" commit -aqm "add submodule"
GIT_SYNC \ GIT_SYNC \
--submodules=shallow \ --period=100ms \
--wait=0.1 \
--repo="file://$REPO" \ --repo="file://$REPO" \
--root="$ROOT" \ --root="$ROOT" \
--dest="link" \ --dest="link" \
--submodules=shallow \
> "$DIR"/log."$TESTCASE" 2>&1 & > "$DIR"/log."$TESTCASE" 2>&1 &
sleep 3 sleep 3
assert_link_exists "$ROOT"/link assert_link_exists "$ROOT"/link
@ -1032,13 +1035,13 @@ IP=$(docker inspect "$CTR" | jq -r .[0].NetworkSettings.IPAddress)
git -C "$REPO" commit -qam "$TESTCASE" git -C "$REPO" commit -qam "$TESTCASE"
GIT_SYNC \ GIT_SYNC \
--one-time \ --one-time \
--ssh \
--ssh-known-hosts=false \
--repo="test@$IP:/src" \ --repo="test@$IP:/src" \
--branch=master \ --branch=master \
--rev=HEAD \ --rev=HEAD \
--root="$ROOT" \ --root="$ROOT" \
--dest="link" \ --dest="link" \
--ssh \
--ssh-known-hosts=false \
> "$DIR"/log."$TESTCASE" 2>&1 > "$DIR"/log."$TESTCASE" 2>&1
assert_link_exists "$ROOT"/link assert_link_exists "$ROOT"/link
assert_file_exists "$ROOT"/link/file assert_file_exists "$ROOT"/link/file