_loadCodeTreeInternal(opts, transform, cb) {
    const folders = { '': [] };
    const { path, repo, node } = opts;

    opts.encodedBranch = opts.encodedBranch || encodeURIComponent(decodeURIComponent(repo.branch));

    this._getTree(path, opts, (err, tree) => {
      if (err) return cb(err);

      const treeMap = this.collectTree(tree);

      this._getSubmodules(tree, opts, (err, submodules) => {
        if (err) return cb(err);

        // eslint-disable-next-line no-param-reassign
        submodules = submodules || {};

        // eslint-disable-next-line complexity
        const nextChunk = async (iteration = 0) => {
          const CHUNK_SIZE = 300;

          for (let i = 0; i < CHUNK_SIZE; i++) {
            let item = tree[iteration * CHUNK_SIZE + i];

            // We're done
            if (item === undefined) {
              let treeData = folders[''];
              treeData = this._sort(treeData);
              if (!opts.node) {
                treeData = this._collapse(treeData);
              }
              return cb(null, treeData);
            }

            // Runs transform requested by subclass
            if (transform) {
              item = transform(item);
            }

            // If lazy load and has parent, prefix with parent path
            // gitlab default is lazyload
            // so gitlab url should not append parent path
            if (node && node.path) {
              if (!item.path.startsWith(`${node.path}/`)) {
                item.path = node.path + '/' + item.path;
              }
            }

            const path = item.path || '';
            const type = item.type;
            const index = path.lastIndexOf('/');
            const name = deXss(path.substring(index + 1)); // Sanitizes, closes #9
            const attr = {};

            item.id = NODE_PREFIX + path;
            item.text = name;
            item.li_attr = {
              title: path,
            };

            // Uses `type` as class name for tree node
            item.icon = type;

            // eslint-disable-next-line no-await-in-loop
            await gitMaster.setNodeIconAndText(this, item);

            if (item.patch) {
              item.text += `<span class="gitmaster-patch">${this.buildPatchHtml(item)}</span>`;
            }

            if (node) {
              folders[''].push(item);
            } else {
              folders[path.substring(0, index)].push(item);
            }

            if (type === 'tree' || type === 'blob') {
              if (type === 'tree') {
                if (node) {
                  item.children = true;
                } else {
                  // eslint-disable-next-line no-multi-assign
                  folders[item.path] = item.children = [];
                }

                if (treeMap[path]) {
                  attr['data-file-count'] = treeMap[path];
                }
              } else if (type === 'blob' && item.size) {
                const parsedSize = convertSizeToHumanReadableFormat(item.size, 0);
                attr['data-file-size'] = parsedSize.size + parsedSize.measure;
              }

              // If item is part of a PR, jump to that file's diff
              if (item.patch && typeof item.patch.diffId === 'number') {
                const url = this._getPatchHref(repo, item.patch);

                attr.href = url;
                attr['data-download-url'] = item.url;
                attr['data-download-filename'] = name;
              } else {
                // Encodes but retains the slashes, see #274
                const encodedPath = path
                  .split('/')
                  .map(encodeURIComponent)
                  .join('/');
                const url = this.getItemHref(repo, type, encodedPath, opts.encodedBranch);

                attr.href = url;
                attr['data-download-url'] = url;
                attr['data-download-filename'] = name;
              }
            } else if (type === 'commit') {
              let moduleUrl = submodules[item.path];

              if (moduleUrl) {
                // Fixes #105
                // Special handling for submodules hosted in GitHub
                // eslint-disable-next-line no-bitwise
                if (moduleUrl.indexOf('github.com') !== -1) {
                  moduleUrl =
                    moduleUrl
                      .replace(/^git(:\/\/|@)/, window.location.protocol + '//')
                      .replace('github.com:', 'github.com/')
                      .replace(/.git$/, '') +
                    '/tree/' +
                    item.sha;
                  item.text = `${name} @ ${item.sha.substr(0, 7)}`;
                }

                attr.href = moduleUrl;
                attr['data-skip-pjax'] = true;
              }
            }

            item.a_attr = attr;
          }

          setTimeout(() => nextChunk(iteration + 1));
        };

        nextChunk();
      });
    });
  }
Loads the code tree of a repository.
@param {Object} opts: {
                 path: the starting path to load the tree,
                 repo: the current repository,
                 node (optional): the selected node (null/false to load entire tree),
                 token (optional): the personal access token
                }
@param {Function} transform(item)
@param {Function} cb(err: error, tree: Array[Array|item])
@api protected