Browse Source

HPCC-9984 Compile direct from a version control system

Add support for bare repositories into the git file reader.

Note that this change means that the {branch} part of the git file
name is no longer optional. To refer to HEAD (on a non-bare repository)
you can use {}

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 11 năm trước cách đây
mục cha
commit
dd93cfe6ca
1 tập tin đã thay đổi với 24 bổ sung19 xóa
  1. 24 19
      common/remote/hooks/git/gitfile.cpp

+ 24 - 19
common/remote/hooks/git/gitfile.cpp

@@ -28,6 +28,7 @@
 /*
 /*
  * Direct access to files in git repositories, by revision, without needing to check them out first
  * Direct access to files in git repositories, by revision, without needing to check them out first
  * Installs hooks into createIFile, spotting filenames of the form /my/directory/.git/{revision}/path/within/git
  * Installs hooks into createIFile, spotting filenames of the form /my/directory/.git/{revision}/path/within/git
+ * Bare repositories of the form  /my/directory.git/{revision}/path/within/git also supported
  */
  */
 
 
 IDirectoryIterator *createGitRepositoryDirectoryIterator(const char *gitFileName, const char *mask=NULL, bool sub=false,bool includedirs=false);
 IDirectoryIterator *createGitRepositoryDirectoryIterator(const char *gitFileName, const char *mask=NULL, bool sub=false,bool includedirs=false);
@@ -35,25 +36,21 @@ IDirectoryIterator *createGitRepositoryDirectoryIterator(const char *gitFileName
 static void splitGitFileName(const char *fullName, StringAttr &gitDir, StringAttr &revision, StringAttr &relPath)
 static void splitGitFileName(const char *fullName, StringAttr &gitDir, StringAttr &revision, StringAttr &relPath)
 {
 {
     assertex(fullName);
     assertex(fullName);
-    const char *git = strstr(fullName, PATHSEPSTR ".git" PATHSEPSTR);
+    const char *git = strstr(fullName, ".git" PATHSEPSTR "{" );
     assertex(git);
     assertex(git);
-    const char *tail = git+6;
+    const char *tail = git+5;
     gitDir.set(fullName, tail-fullName);
     gitDir.set(fullName, tail-fullName);
-    if (*tail=='{')
-    {
+    assertex (*tail=='{');
+    tail++;
+    const char *end = strchr(tail, '}');
+    if (!end)
+        throw MakeStringException(0, "Invalid git repository filename - no matching } found");
+    revision.set(tail, end - tail);
+    tail = end+1;
+    if (*tail==PATHSEPCHAR)
         tail++;
         tail++;
-        const char *end = strchr(tail, '}');
-        if (!end)
-            throw MakeStringException(0, "Invalid git repository filename - no matching } found");
-        revision.set(tail, end - tail);
-        tail = end+1;
-        if (*tail==PATHSEPCHAR)
-            tail++;
-        else if (*tail != 0)
-            throw MakeStringException(0, "Invalid git repository filename - " PATHSEPSTR " expected after }");
-    }
-    else
-        revision.clear();
+    else if (*tail != 0)
+        throw MakeStringException(0, "Invalid git repository filename - " PATHSEPSTR " expected after }");
     if (tail && *tail)
     if (tail && *tail)
     {
     {
         StringBuffer s(tail);
         StringBuffer s(tail);
@@ -62,13 +59,17 @@ static void splitGitFileName(const char *fullName, StringAttr &gitDir, StringAtt
     }
     }
     else
     else
         relPath.clear();
         relPath.clear();
+    // Check it's a valid git repository
+    StringBuffer configName(gitDir);
+    configName.append("config");
+    if (!checkFileExists(configName.str()))
+        throw MakeStringException(0, "Invalid git repository - config file %s not found", configName.str());
 }
 }
 
 
 static StringBuffer & buildGitFileName(StringBuffer &fullname, const char *gitDir, const char *revision, const char *relPath)
 static StringBuffer & buildGitFileName(StringBuffer &fullname, const char *gitDir, const char *revision, const char *relPath)
 {
 {
     fullname.append(gitDir);
     fullname.append(gitDir);
-    if (revision && *revision)
-        fullname.append('{').append(revision).append('}').append(PATHSEPCHAR);
+    fullname.append('{').append(revision).append('}').append(PATHSEPCHAR);
     if (relPath && *relPath)
     if (relPath && *relPath)
         fullname.append(relPath);
         fullname.append(relPath);
     return fullname;
     return fullname;
@@ -267,6 +268,10 @@ static IFile *createGitFile(const char *gitFileName)
     StringBuffer fname(gitFileName);
     StringBuffer fname(gitFileName);
     assertex(fname.length());
     assertex(fname.length());
     removeTrailingPathSepChar(fname);
     removeTrailingPathSepChar(fname);
+    StringAttr gitDirectory, revision, relDir;
+    splitGitFileName(fname, gitDirectory, revision, relDir);
+    if (relDir.isEmpty())
+        return new GitRepositoryFile(fname, 0, true, true);  // Special case the root - ugly but apparently necessary
     Owned<IDirectoryIterator> dir = createGitRepositoryDirectoryIterator(fname, NULL, false, true);
     Owned<IDirectoryIterator> dir = createGitRepositoryDirectoryIterator(fname, NULL, false, true);
     if (dir->first())
     if (dir->first())
     {
     {
@@ -427,7 +432,7 @@ public:
 protected:
 protected:
     static bool isGitFileName(const char *fileName)
     static bool isGitFileName(const char *fileName)
     {
     {
-        if (fileName && strstr(fileName, PATHSEPSTR ".git" PATHSEPSTR))
+        if (fileName && strstr(fileName, ".git" PATHSEPSTR "{"))
             return true;
             return true;
         return false;
         return false;
     }
     }