whole_func_string: function (path/*, options*/) {
      return this._getFileId(path).then((id) => {
        let query, fields, data, etagWithoutQuotes, itemsMap;
        if (! id) {
          return Promise.resolve({statusCode: 404});
        }
  
        query = '\'' + id + '\' in parents';
        fields = 'items(downloadUrl,etag,fileSize,id,mimeType,title)';
        return this._request('GET', BASE_URL + '/drive/v2/files?'
            + 'q=' + encodeURIComponent(query)
            + '&fields=' + encodeURIComponent(fields)
            + '&maxResults=1000',
            {})
        .then((response) => {
          if (response.status !== 200) {
            return Promise.reject('request failed or something: ' + response.status);
          }
  
          try {
            data = JSON.parse(response.responseText);
          } catch(e) {
            return Promise.reject('non-JSON response from GoogleDrive');
          }
  
          itemsMap = {};
          for (const item of data.items) {
            etagWithoutQuotes = removeQuotes(item.etag);
            if (item.mimeType === GD_DIR_MIME_TYPE) {
              this._fileIdCache.set(path + item.title + '/', item.id);
              itemsMap[item.title + '/'] = {
                ETag: etagWithoutQuotes
              };
            } else {
              this._fileIdCache.set(path + item.title, item.id);
              itemsMap[item.title] = {
                ETag: etagWithoutQuotes,
                'Content-Type': item.mimeType,
                'Content-Length': item.fileSize
              };
            }
          }
  
          // FIXME: add revision of folder!
          return Promise.resolve({statusCode: 200, body: itemsMap, contentType: RS_DIR_MIME_TYPE, revision: undefined});
        });
      });
    }
func_code_string: function (path/*, options*/) {
      return this._getFileId(path).then((id) => {
        let query, fields, data, etagWithoutQuotes, itemsMap;
        if (! id) {
          return Promise.resolve({statusCode: 404});
        }
  
        query = '\'' + id + '\' in parents';
        fields = 'items(downloadUrl,etag,fileSize,id,mimeType,title)';
        return this._request('GET', BASE_URL + '/drive/v2/files?'
            + 'q=' + encodeURIComponent(query)
            + '&fields=' + encodeURIComponent(fields)
            + '&maxResults=1000',
            {})
        .then((response) => {
          if (response.status !== 200) {
            return Promise.reject('request failed or something: ' + response.status);
          }
  
          try {
            data = JSON.parse(response.responseText);
          } catch(e) {
            return Promise.reject('non-JSON response from GoogleDrive');
          }
  
          itemsMap = {};
          for (const item of data.items) {
            etagWithoutQuotes = removeQuotes(item.etag);
            if (item.mimeType === GD_DIR_MIME_TYPE) {
              this._fileIdCache.set(path + item.title + '/', item.id);
              itemsMap[item.title + '/'] = {
                ETag: etagWithoutQuotes
              };
            } else {
              this._fileIdCache.set(path + item.title, item.id);
              itemsMap[item.title] = {
                ETag: etagWithoutQuotes,
                'Content-Type': item.mimeType,
                'Content-Length': item.fileSize
              };
            }
          }
  
          // FIXME: add revision of folder!
          return Promise.resolve({statusCode: 200, body: itemsMap, contentType: RS_DIR_MIME_TYPE, revision: undefined});
        });
      });
    }
func_documentation_string: Request a directory.
  
  @param {string} path - Directory path
  @param {Object} options
  @returns {Promise} Resolves with an object containing the status code,
  body and content-type
  
  @private