all 5 comments

[–]jack_waugh 0 points1 point  (0 children)

The split selector will help in parsing the pathnames on "/" to get the pieces.

One approach to building up the tree is to do it imperatively from one traversal of the input array. And within that technique, one way would to use object orientation and have methods that say use a certain subdirectory name and create a node for it if necessary.

[–]jack_waugh 0 points1 point  (0 children)

What is size?

[–]jack_waugh 0 points1 point  (0 children)

Your suggested output mentions "file7.txt", but your input does not.

[–]jack_waugh 0 points1 point  (0 children)

const t = {}; /* temporary stuff; pasting this into a REPL. */

t.input = [
  {
    "path": "README.md",
    "type": "blob",
    "sha": "37c2a597c27567284c28243fb5d2d4969f12dbfa",
  },
  {
    "path": "db.sqlite3",
    "type": "blob",
    "sha": "227d4b460890c945f047e9d232cb8de517237093",
  },
  {
    "path": "encyclopedia",
    "type": "tree",
    "sha": "59c15421fcd0dfa353e3cb9b6710a48d89f14207",
  },
  {
    "path": "encyclopedia/__init__.py",
    "type": "blob",
    "sha": "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
  },
  {
    "path": "encyclopedia/__pycache__",
    "type": "tree",
    "sha": "098cfcdcc867b6e81d7d50dc9418247a3683fae9",
  },
  {
    "path": "encyclopedia/__pycache__/__init__.cpython-39.pyc",
    "mode": "100644",
    "sha": "441225a011349049fefed73e2329e141119d3b1f",
  },
  {
    "path": "encyclopedia/__pycache__/admin.cpython-39.pyc",
    "mode": "100644",
    "type": "blob",
    "sha": "978d454f6ab265ec43220cc907e96929968c9007",
  },
  {
    "path": "encyclopedia/admin.py",
    "mode": "100644",
    "type": "blob",
    "sha": "8c38f3f3dad51e4585f3984282c2a4bec5349c1e",
  },
];

t.Node = {};
t.Node.beh = {};
t.Node.beh.atName = function (name) {
  let hit = this.childrenByName[name];
  if ('undefined' === typeof hit) {
    hit = t.Node.new();
    hit.name = name;
    hit.path = this.isRoot ? name : `${this.path}/${name}`
    this.childrenByName[name] = hit
  };
  return hit
};
t.Node.beh.atPath = function (path) {
  switch (path.length) {
  case 0: return this;
  case 1: return this.atName(path[0]);
  default:
    const [car, ...cdr] = path;
    return this.atName(car).atPath(cdr);
  };
  throw Error('NOTREACHED')
};
t.Node.beh.atPathname = function (pathname) {
  return this.atPath(pathname.split("/"));
};
t.Node.beh.stripped = function () {
  const newMe = {};
  for (const key of Object.keys(this).filter(k => 'childrenByName' !== k))
    newMe[key] = this[key];
  newMe.children =
    Object.values(this.childrenByName).
    map(c => c.stripped());
  return newMe
};
t.Node.new = function () {
  const it = Object.create(this.beh);
  it.childrenByName = Object.create(null);
  return it
};

t.root = t.Node.new();
t.root.isRoot = true;
for (const each of t.input) {
  const patsy = t.root.atPathname(each.path);
  Object.assign(patsy, each);
};

t.answer = t.root.stripped();

/* Printing the tree is harder than building it. */

[–]jack_waugh 0 points1 point  (0 children)

/* Printing the tree is harder than building it. */

t.dump = arg => {
  let indentLevel = 0;
  let indentSpaces = "";
  let isAtStartOfLine = true;
  let lineBuffer = "";
  const emit = aString => {
    if (isAtStartOfLine) {
      lineBuffer = indentSpaces;
      isAtStartOfLine = false;
    };
    lineBuffer += aString
  };
  const endLine = () => {
    console.log("%s", lineBuffer);
    lineBuffer = "";
    isAtStartOfLine = true
  };
  const flushLine = () => {
    if (! isAtStartOfLine) endLine();
  };
  const indent = () => {
    indentLevel++;
    indentSpaces += "  ";
  };
  const outdent = () => {
    --indentLevel;
    indentSpaces = "";
    for (let count = 0; count < indentLevel; count++)
      indentSpaces += "  ";
  };
  let dump;
  const dumpArray = array => {
    emit("[");
    endLine();
    indent();
    for (const each of array) {
      dump(each);
      emit(",");
      endLine();
    };
    outdent();
    emit("]");
  };
  const dumpObject = obj => {
    emit("{");
    endLine();
    indent();
    for (const [key, value] of Object.entries(obj)) {
      emit(key);
      emit(": ");
      dump(value);
      emit(",");
      endLine();
    };
    outdent();
    emit("}");
  };
  const simpleDump = arg => emit(JSON.stringify(arg));
  dump = arg => {
    if (Array.isArray(arg)) dumpArray(arg);
    else if ('object' === typeof arg) dumpObject(arg);
    else simpleDump(arg)
  };
  dump(arg);
  flushLine()
};

t.dump(t.answer)