Skip to content

graphql: Add `GitCommit.Path` resolver

Administrator requested to merge ef/commit-tree into main

Created by: efritz

This PR adds a new path resolver as as sibling to tree and blob on git commit. Currently, if we have a path in a repo but do not know whether it is a blob or a tree, we cannot query the API to determine which it is: both resolvers have a non-intersecting set of conditions that return an error to the user.

In order not to encourage users to trust requests containing partial errors, we should allow a resolver to gather a git tree or blob resolver by path name only, and introspect the type.

See the following API requests/responses for what I've come up with so far.

Open questions/feedback requests include:

  • Is there another way to query this data I'm not aware of?
  • __typename is always GitTree in the new resolver. Is this odd or worth documenting?

Blobs (current behavior)

Success:

{
  repository(name: "github.com/sourcegraph/sourcegraph") {
    commit(rev: "HEAD") {
      blob(path: "enterprise/cmd/server/main.go") {
        path
        isDirectory
      }
    }
  }
}
{
  "data": {
    "repository": {
      "commit": {
        "blob": {
          "path": "enterprise/cmd/server/main.go",
          "isDirectory": false
        }
      }
    }
  }
}

Blob on a directory returns an error:

{
  repository(name: "github.com/sourcegraph/sourcegraph") {
    commit(rev: "HEAD") {
      blob(path: "enterprise") {
        path
        isDirectory
      }
    }
  }
}
{
  "errors": [
    {
      "message": "not a blob: \"enterprise\"",
      "path": [
        "repository",
        "commit",
        "blob"
      ]
    }
  ],
  "data": {
    "repository": {
      "commit": {
        "blob": null
      }
    }
  }
}

Trees (current behavior)

Success:

{
  repository(name: "github.com/sourcegraph/sourcegraph") {
    commit(rev: "HEAD") {
      tree(path: "enterprise") {
        path
        isDirectory
      }
    }
  }
}
{
  "data": {
    "repository": {
      "commit": {
        "tree": {
          "path": "enterprise",
          "isDirectory": true
        }
      }
    }
  }
}

Tree on a blob returns an error:

{
  repository(name: "github.com/sourcegraph/sourcegraph") {
    commit(rev: "HEAD") {
      tree(path: "enterprise/cmd/server/main.go") {
        path
        isDirectory
      }
    }
  }
}
{
  "errors": [
    {
      "message": "not a directory: \"enterprise/cmd/server/main.go\"",
      "path": [
        "repository",
        "commit",
        "tree"
      ]
    }
  ],
  "data": {
    "repository": {
      "commit": {
        "tree": null
      }
    }
  }
}

Paths (new behavior)

Success (blob):

{
  repository(name: "github.com/sourcegraph/sourcegraph") {
    commit(rev: "HEAD") {
      path(path: "enterprise/cmd/server/main.go") {
        ... on GitTree {
          __typename
          path
          isDirectory
        }
        ... on GitBlob {
          __typename
          path
          isDirectory
        }
      }
    }
  }
}
{
  "data": {
    "repository": {
      "commit": {
        "path": {
          "__typename": "GitTree",
          "path": "enterprise/cmd/server/main.go",
          "isDirectory": false
        }
      }
    }
  }
}

Success (tree):

{
  repository(name: "github.com/sourcegraph/sourcegraph") {
    commit(rev: "HEAD") {
      path(path: "enterprise") {
        ... on GitTree {
          __typename
          path
          isDirectory
        }
        ... on GitBlob {
          __typename
          path
          isDirectory
        }
      }
    }
  }
}
{
  "data": {
    "repository": {
      "commit": {
        "path": {
          "__typename": "GitTree",
          "path": "enterprise",
          "isDirectory": true
        }
      }
    }
  }
}

Test plan

Tested local API via console by hand. See PR description.

Merge request reports

Loading