Browse code

Merge "Add GIT_TIMEOUT variable to watch git operations"

Jenkins authored on 2014/02/27 13:31:40
Showing 2 changed files
... ...
@@ -527,16 +527,16 @@ function git_clone {
527 527
         if [[ ! -d $GIT_DEST ]]; then
528 528
             [[ "$ERROR_ON_CLONE" = "True" ]] && \
529 529
                 die $LINENO "Cloning not allowed in this configuration"
530
-            git clone $GIT_REMOTE $GIT_DEST
530
+            git_timed clone $GIT_REMOTE $GIT_DEST
531 531
         fi
532 532
         cd $GIT_DEST
533
-        git fetch $GIT_REMOTE $GIT_REF && git checkout FETCH_HEAD
533
+        git_timed fetch $GIT_REMOTE $GIT_REF && git checkout FETCH_HEAD
534 534
     else
535 535
         # do a full clone only if the directory doesn't exist
536 536
         if [[ ! -d $GIT_DEST ]]; then
537 537
             [[ "$ERROR_ON_CLONE" = "True" ]] && \
538 538
                 die $LINENO "Cloning not allowed in this configuration"
539
-            git clone $GIT_REMOTE $GIT_DEST
539
+            git_timed clone $GIT_REMOTE $GIT_DEST
540 540
             cd $GIT_DEST
541 541
             # This checkout syntax works for both branches and tags
542 542
             git checkout $GIT_REF
... ...
@@ -545,7 +545,7 @@ function git_clone {
545 545
             cd $GIT_DEST
546 546
             # set the url to pull from and fetch
547 547
             git remote set-url origin $GIT_REMOTE
548
-            git fetch origin
548
+            git_timed fetch origin
549 549
             # remove the existing ignored files (like pyc) as they cause breakage
550 550
             # (due to the py files having older timestamps than our pyc, so python
551 551
             # thinks the pyc files are correct using them)
... ...
@@ -570,6 +570,37 @@ function git_clone {
570 570
     git show --oneline | head -1
571 571
 }
572 572
 
573
+# git can sometimes get itself infinitely stuck with transient network
574
+# errors or other issues with the remote end.  This wraps git in a
575
+# timeout/retry loop and is intended to watch over non-local git
576
+# processes that might hang.  GIT_TIMEOUT, if set, is passed directly
577
+# to timeout(1); otherwise the default value of 0 maintains the status
578
+# quo of waiting forever.
579
+# usage: git_timed <git-command>
580
+function git_timed() {
581
+    local count=0
582
+    local timeout=0
583
+
584
+    if [[ -n "${GIT_TIMEOUT}" ]]; then
585
+        timeout=${GIT_TIMEOUT}
586
+    fi
587
+
588
+    until timeout -s SIGINT ${timeout} git "$@"; do
589
+        # 124 is timeout(1)'s special return code when it reached the
590
+        # timeout; otherwise assume fatal failure
591
+        if [[ $? -ne 124 ]]; then
592
+            die $LINENO "git call failed: [git $@]"
593
+        fi
594
+
595
+        count=$(($count + 1))
596
+        warn "timeout ${count} for git call: [git $@]"
597
+        if [ $count -eq 3 ]; then
598
+            die $LINENO "Maximum of 3 git retries reached"
599
+        fi
600
+        sleep 5
601
+    done
602
+}
603
+
573 604
 # git update using reference as a branch.
574 605
 # git_update_branch ref
575 606
 function git_update_branch() {
... ...
@@ -600,7 +631,7 @@ function git_update_tag() {
600 600
 
601 601
     git tag -d $GIT_TAG
602 602
     # fetching given tag only
603
-    git fetch origin tag $GIT_TAG
603
+    git_timed fetch origin tag $GIT_TAG
604 604
     git checkout -f $GIT_TAG
605 605
 }
606 606
 
... ...
@@ -80,6 +80,17 @@ fi
80 80
 # (currently only implemented for MySQL backend)
81 81
 DATABASE_QUERY_LOGGING=$(trueorfalse True $DATABASE_QUERY_LOGGING)
82 82
 
83
+# Set a timeout for git operations.  If git is still running when the
84
+# timeout expires, the command will be retried up to 3 times.  This is
85
+# in the format for timeout(1);
86
+#
87
+#  DURATION is a floating point number with an optional suffix: 's'
88
+#  for seconds (the default), 'm' for minutes, 'h' for hours or 'd'
89
+#  for days.
90
+#
91
+# Zero disables timeouts
92
+GIT_TIMEOUT=${GIT_TIMEOUT:-0}
93
+
83 94
 # Repositories
84 95
 # ------------
85 96