Patchwork [V2] test-lfs-test-server: add a testcase for `hg serve`

login
register
mail settings
Submitter Matt Harbison
Date March 30, 2018, 1:51 a.m.
Message ID <c55981fe1afb8e6e310b.1522374701@Envy>
Download mbox | patch
Permalink /patch/29944/
State Superseded
Headers show

Comments

Matt Harbison - March 30, 2018, 1:51 a.m.
# HG changeset patch
# User Matt Harbison <matt_harbison@yahoo.com>
# Date 1521268666 14400
#      Sat Mar 17 02:37:46 2018 -0400
# Node ID c55981fe1afb8e6e310bcbd0094cfd7ba571921b
# Parent  0348c778bf70ae096707e2fd39fd1c79e694dfab
test-lfs-test-server: add a testcase for `hg serve`

I haven't figured out yet how to make the authentication checks work for a
specific list of users, so the 'web.allow-push' list is wildcarded.  (It appears
that the client doesn't react to a 401 by sending authentication data, which may
be caused in part by not having all of the headers in httpbasicauthhandler's
http_error_auth_reqed(), compared to a run of test-http.t.  But in any case, we
should probably have a separate set of tests for various authentication
scenarios.  As it is, without the wildcard, no push access is granted.)

The reason for aborting differs between hg and git servers, around line 452.
This is a bug in the client side, which is checking for a missing 'download'
action before checking for an 'error' key.  I'll submit that fix once this
lands.

Patch

diff --git a/tests/test-lfs-test-server.t b/tests/test-lfs-test-server.t
--- a/tests/test-lfs-test-server.t
+++ b/tests/test-lfs-test-server.t
@@ -1,13 +1,26 @@ 
+#testcases git-server hg-server
+
+#if git-server
 #require lfs-test-server
+#else
+#require serve
+#endif
 
+#if git-server
   $ LFS_LISTEN="tcp://:$HGPORT"
   $ LFS_HOST="localhost:$HGPORT"
   $ LFS_PUBLIC=1
   $ export LFS_LISTEN LFS_HOST LFS_PUBLIC
-#if no-windows
+#else
+  $ LFS_HOST="localhost:$HGPORT/.git/info/lfs"
+#endif
+
+#if no-windows git-server
   $ lfs-test-server &> lfs-server.log &
   $ echo $! >> $DAEMON_PIDS
-#else
+#endif
+
+#if windows git-server
   $ cat >> $TESTTMP/spawn.py <<EOF
   > import os
   > import subprocess
@@ -29,10 +42,23 @@ 
   > [extensions]
   > lfs=
   > [lfs]
-  > url=http://foo:bar@$LFS_HOST/
+  > url=http://foo:bar@$LFS_HOST
   > track=all()
+  > [web]
+  > push_ssl = False
+  > allow-push = *
   > EOF
 
+Use a separate usercache, otherwise the server sees what the client commits, and
+never requests a transfer.
+
+#if hg-server
+  $ hg init server
+  $ hg --config "lfs.usercache=$TESTTMP/servercache" -R server serve -d \
+  >    -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
+  $ cat hg.pid >> $DAEMON_PIDS
+#endif
+
   $ hg init repo1
   $ cd repo1
   $ echo THIS-IS-LFS > a
@@ -55,9 +81,11 @@  store.
   listing keys for "bookmarks"
   lfs: computing set of blobs to upload
   Status: 200
-  Content-Length: 309
+  Content-Length: 309 (git-server !)
+  Content-Length: 350 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
@@ -67,19 +95,23 @@  store.
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
+            "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (git-server !)
+            "href": "http://localhost:$HGPORT/.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (hg-server !)
           }
         }
         "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
         "size": 12
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
   lfs: uploading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
-  Status: 200
+  Status: 200 (git-server !)
+  Status: 201 (hg-server !)
   Content-Length: 0
   Content-Type: text/plain; charset=utf-8
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
   lfs: uploaded 1 files (12 bytes)
   1 changesets found
@@ -125,9 +157,11 @@  Clear the cache to force a download
    branchmerge: False, force: False, partial: False
    ancestor: 000000000000, local: 000000000000+, remote: 99a7098854a3
   Status: 200
-  Content-Length: 311
+  Content-Length: 311 (git-server !)
+  Content-Length: 352 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
@@ -137,19 +171,22 @@  Clear the cache to force a download
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
+            "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
           }
         }
         "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
         "size": 12
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
   lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
   Status: 200
   Content-Length: 12
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
   lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
    a: remote created -> g
@@ -157,7 +194,10 @@  Clear the cache to force a download
   lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
-When the server has some blobs already
+When the server has some blobs already.  `hg serve` doesn't offer to upload
+blobs that it already knows about.  Note that lfs-test-server is simply
+toggling the action to 'download'.  The Batch API spec says it should omit the
+actions property completely.
 
   $ hg mv a b
   $ echo ANOTHER-LARGE-FILE > c
@@ -176,21 +216,23 @@  When the server has some blobs already
   listing keys for "bookmarks"
   lfs: computing set of blobs to upload
   Status: 200
-  Content-Length: 901
+  Content-Length: 901 (git-server !)
+  Content-Length: 755 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
-        "actions": {
-          "download": {
-            "expires_at": "$ISO_8601_DATE_TIME$"
-            "header": {
-              "Accept": "application/vnd.git-lfs"
-            }
-            "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
-          }
-        }
+        "actions": { (git-server !)
+          "download": { (git-server !)
+            "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
+            "header": { (git-server !)
+              "Accept": "application/vnd.git-lfs" (git-server !)
+            } (git-server !)
+            "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (git-server !)
+          } (git-server !)
+        } (git-server !)
         "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
         "size": 12
       }
@@ -201,7 +243,7 @@  When the server has some blobs already
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
+            "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
           }
         }
         "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
@@ -214,26 +256,31 @@  When the server has some blobs already
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
+            "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
           }
         }
         "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
         "size": 19
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
   lfs: need to transfer 2 objects (39 bytes)
   lfs: uploading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
-  Status: 200
+  Status: 200 (git-server !)
+  Status: 201 (hg-server !)
   Content-Length: 0
   Content-Type: text/plain; charset=utf-8
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
   lfs: uploading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
-  Status: 200
+  Status: 200 (git-server !)
+  Status: 201 (hg-server !)
   Content-Length: 0
   Content-Type: text/plain; charset=utf-8
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
   lfs: uploaded 2 files (39 bytes)
   1 changesets found
@@ -281,9 +328,11 @@  Clear the cache to force a download
    branchmerge: False, force: False, partial: False
    ancestor: 99a7098854a3, local: 99a7098854a3+, remote: dfca2c9e2ef2
   Status: 200
-  Content-Length: 608
+  Content-Length: 608 (git-server !)
+  Content-Length: 670 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
@@ -293,7 +342,7 @@  Clear the cache to force a download
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
+            "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
           }
         }
         "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
@@ -306,27 +355,32 @@  Clear the cache to force a download
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
+            "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
           }
         }
         "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
         "size": 19
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
   lfs: need to transfer 2 objects (39 bytes)
   lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
   Status: 200
   Content-Length: 20
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
   lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
   lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
   Status: 200
   Content-Length: 19
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
   lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
    b: remote created -> g
@@ -341,45 +395,61 @@  Clear the cache to force a download
   3 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 Test a corrupt file download, but clear the cache first to force a download.
+`hg serve` indicates a corrupt file without transferring it, unlike
+lfs-test-server.
 
   $ rm -rf `hg config lfs.usercache`
+#if git-server
   $ cp $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
   $ echo 'damage' > $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
+#else
+  $ cp $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
+  $ echo 'damage' > $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
+#endif
   $ rm ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
   $ rm ../repo1/*
 
+TODO: give the proper error indication from `hg serve`
+
   $ hg --repo ../repo1 update -C tip --debug
   http auth: user foo, password ***
   resolving manifests
    branchmerge: False, force: True, partial: False
    ancestor: dfca2c9e2ef2+, local: dfca2c9e2ef2+, remote: dfca2c9e2ef2
   Status: 200
-  Content-Length: 311
+  Content-Length: 311 (git-server !)
+  Content-Length: 183 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
-        "actions": {
-          "download": {
-            "expires_at": "$ISO_8601_DATE_TIME$"
-            "header": {
-              "Accept": "application/vnd.git-lfs"
-            }
-            "href": "http://localhost:$HGPORT/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
-          }
+        "actions": { (git-server !)
+          "download": { (git-server !)
+            "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
+            "header": { (git-server !)
+              "Accept": "application/vnd.git-lfs" (git-server !)
+            } (git-server !)
+            "href": "http://localhost:$HGPORT/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (git-server !)
+          } (git-server !)
+        "error": { (hg-server !)
+          "code": 422 (hg-server !)
+          "message": "The object is corrupt" (hg-server !)
         }
         "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
         "size": 19
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
-  lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
-  Status: 200
-  Content-Length: 7
-  Content-Type: text/plain; charset=utf-8
-  Date: $HTTP_DATE$
-  abort: corrupt remote lfs object: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
+  lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes) (git-server !)
+  Status: 200 (git-server !)
+  Content-Length: 7 (git-server !)
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Date: $HTTP_DATE$ (git-server !)
+  abort: corrupt remote lfs object: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (git-server !)
+  abort: LFS server error. Remote object for "c" not found: *! (glob) (hg-server !)
   [255]
 
 The corrupted blob is not added to the usercache or local store
@@ -388,7 +458,11 @@  The corrupted blob is not added to the u
   [1]
   $ test -f `hg config lfs.usercache`/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
   [1]
+#if git-server
   $ cp blob $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
+#else
+  $ cp blob $TESTTMP/server/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
+#endif
 
 Test a corrupted file upload
 
@@ -408,9 +482,11 @@  Test a corrupted file upload
   listing keys for "bookmarks"
   lfs: computing set of blobs to upload
   Status: 200
-  Content-Length: 309
+  Content-Length: 309 (git-server !)
+  Content-Length: 350 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
@@ -420,13 +496,14 @@  Test a corrupted file upload
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0"
+            "href": "http://localhost:$HGPORT/*/e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0" (glob)
           }
         }
         "oid": "e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0"
         "size": 17
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
   lfs: uploading e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0 (17 bytes)
   abort: detected corrupt lfs object: e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
@@ -439,9 +516,11 @@  Archive will prefetch blobs in a group
   $ hg archive --debug -r 1 ../archive
   http auth: user foo, password ***
   Status: 200
-  Content-Length: 905
+  Content-Length: 905 (git-server !)
+  Content-Length: 988 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
@@ -451,7 +530,7 @@  Archive will prefetch blobs in a group
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
+            "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
           }
         }
         "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
@@ -464,7 +543,7 @@  Archive will prefetch blobs in a group
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
+            "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
           }
         }
         "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
@@ -477,34 +556,41 @@  Archive will prefetch blobs in a group
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
+            "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
           }
         }
         "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
         "size": 19
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
   lfs: need to transfer 3 objects (51 bytes)
   lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
   Status: 200
   Content-Length: 12
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
   lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
   lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
   Status: 200
   Content-Length: 20
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
   lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
   lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
   Status: 200
   Content-Length: 19
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
   lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
   lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
@@ -525,9 +611,11 @@  Cat will prefetch blobs in a group
   $ hg cat --debug -r 1 a b c
   http auth: user foo, password ***
   Status: 200
-  Content-Length: 608
+  Content-Length: 608 (git-server !)
+  Content-Length: 670 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
@@ -537,7 +625,7 @@  Cat will prefetch blobs in a group
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
+            "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
           }
         }
         "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
@@ -550,27 +638,32 @@  Cat will prefetch blobs in a group
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
+            "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
           }
         }
         "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
         "size": 19
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
   lfs: need to transfer 2 objects (31 bytes)
   lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
   Status: 200
   Content-Length: 12
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
   lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
   lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
   Status: 200
   Content-Length: 19
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
   lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
   lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
@@ -592,9 +685,11 @@  Revert will prefetch blobs in a group
   reverting c
   reverting d
   Status: 200
-  Content-Length: 905
+  Content-Length: 905 (git-server !)
+  Content-Length: 988 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
@@ -604,7 +699,7 @@  Revert will prefetch blobs in a group
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
+            "href": "http://localhost:$HGPORT/*/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b" (glob)
           }
         }
         "oid": "31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b"
@@ -617,7 +712,7 @@  Revert will prefetch blobs in a group
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
+            "href": "http://localhost:$HGPORT/*/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19" (glob)
           }
         }
         "oid": "37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19"
@@ -630,34 +725,41 @@  Revert will prefetch blobs in a group
             "header": {
               "Accept": "application/vnd.git-lfs"
             }
-            "href": "http://localhost:$HGPORT/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
+            "href": "http://localhost:$HGPORT/*/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998" (glob)
           }
         }
         "oid": "d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998"
         "size": 19
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
   lfs: need to transfer 3 objects (51 bytes)
   lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
   Status: 200
   Content-Length: 12
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
   lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
   lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
   Status: 200
   Content-Length: 20
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
   lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
   lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
   Status: 200
   Content-Length: 19
-  Content-Type: text/plain; charset=utf-8
+  Content-Type: text/plain; charset=utf-8 (git-server !)
+  Content-Type: application/octet-stream (hg-server !)
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
   lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
   lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
@@ -679,25 +781,31 @@  Check error message when the remote miss
    branchmerge: False, force: True, partial: False
    ancestor: 62fdbaf221c6+, local: 62fdbaf221c6+, remote: ef0564edf47e
   Status: 200
-  Content-Length: 308
+  Content-Length: 308 (git-server !)
+  Content-Length: 186 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
-        "actions": {
-          "upload": {
-            "expires_at": "$ISO_8601_DATE_TIME$"
-            "header": {
-              "Accept": "application/vnd.git-lfs"
-            }
-            "href": "http://localhost:$HGPORT/objects/8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13"
-          }
+        "actions": { (git-server !)
+          "upload": { (git-server !)
+            "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
+            "header": { (git-server !)
+              "Accept": "application/vnd.git-lfs" (git-server !)
+            } (git-server !)
+            "href": "http://localhost:$HGPORT/objects/8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13" (git-server !)
+          } (git-server !)
+        "error": { (hg-server !)
+          "code": 404 (hg-server !)
+          "message": "The object does not exist" (hg-server !)
         }
         "oid": "8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13"
         "size": 6
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
   abort: LFS server error. Remote object for "b" not found:(.*)! (re)
   [255]
@@ -726,16 +834,54 @@  Check error message when object does not
 (Restart the server in a different location so it no longer has the content)
 
   $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+
+#if hg-server
+  $ cat $TESTTMP/access.log $TESTTMP/errors.log
+  $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 201 - (glob)
+  $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 201 - (glob)
+  $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 201 - (glob)
+  $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 HTTP/1.1" 200 - (glob)
+  $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
+#endif
+
   $ rm $DAEMON_PIDS
   $ mkdir $TESTTMP/lfs-server2
   $ cd $TESTTMP/lfs-server2
-#if no-windows
+#if no-windows git-server
   $ lfs-test-server &> lfs-server.log &
   $ echo $! >> $DAEMON_PIDS
-#else
+#endif
+
+#if windows git-server
   $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
 #endif
 
+#if hg-server
+  $ hg init server2
+  $ hg --config "lfs.usercache=$TESTTMP/servercache2" -R server2 serve -d \
+  >    -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
+  $ cat hg.pid >> $DAEMON_PIDS
+#endif
+
   $ cd $TESTTMP
   $ hg --debug clone test test2
   http auth: user foo, password ***
@@ -746,25 +892,31 @@  Check error message when object does not
    branchmerge: False, force: False, partial: False
    ancestor: 000000000000, local: 000000000000+, remote: d2a338f184a8
   Status: 200
-  Content-Length: 308
+  Content-Length: 308 (git-server !)
+  Content-Length: 186 (hg-server !)
   Content-Type: application/vnd.git-lfs+json
   Date: $HTTP_DATE$
+  Server: testing stub value (hg-server !)
   {
     "objects": [
       {
-        "actions": {
-          "upload": {
-            "expires_at": "$ISO_8601_DATE_TIME$"
-            "header": {
-              "Accept": "application/vnd.git-lfs"
-            }
-            "href": "http://localhost:$HGPORT/objects/bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a"
-          }
+        "actions": { (git-server !)
+          "upload": { (git-server !)
+            "expires_at": "$ISO_8601_DATE_TIME$" (git-server !)
+            "header": { (git-server !)
+              "Accept": "application/vnd.git-lfs" (git-server !)
+            } (git-server !)
+            "href": "http://localhost:$HGPORT/objects/bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a" (git-server !)
+          } (git-server !)
+        "error": { (hg-server !)
+          "code": 404 (hg-server !)
+          "message": "The object does not exist" (hg-server !)
         }
         "oid": "bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a"
         "size": 6
       }
     ]
+    "transfer": "basic" (hg-server !)
   }
   abort: LFS server error. Remote object for "a" not found:(.*)! (re)
   [255]