DROP FUNCTION IF EXISTS git_crawl_tree(TEXT); CREATE OR REPLACE FUNCTION git_crawl_tree(root_tree_hash TEXT) RETURNS SETOF "tree_entity" AS $BODY$ DECLARE stack tree_stack_entry[]; current_hash TEXT; current_type OBJTYPE; current_name TEXT; current_parent_name TEXT; current_parent_hash TEXT; current_level INT; current_path TEXT; current_entry tree_stack_entry; child tree_entry; child_type OBJTYPE; BEGIN current_parent_name := ''; current_hash := root_tree_hash; current_name := '/'; current_parent_hash := ''; current_path := ''; current_level = 0; current_type := 'blob'::objtype; current_entry := NULL; SELECT type INTO current_type FROM headers WHERE hash = current_hash; IF current_type != 'tree'::OBJTYPE THEN RETURN; END IF; stack := ARRAY[ ROW ( current_hash, '/', current_type, '', '', 0 )::tree_stack_entry ]; LOOP IF array_length(stack, 1) = 0 OR array_length(stack, 1) IS NULL THEN EXIT; END IF; current_entry = stack[1]; stack = stack[2:array_length(stack, 1)]; current_hash = current_entry.hash; current_name = current_entry.name; current_type = current_entry.type; current_parent_name = current_entry.parent_name; current_parent_hash = current_entry.parent_hash; current_path = current_parent_name; current_level = current_entry.level; IF current_parent_hash IS NOT NULL AND length(current_parent_hash) = 0 THEN current_parent_hash = NULL; END IF; IF current_name != '/' AND substring(current_path FROM length(current_path) - 1) != '/' THEN current_path = current_path || '/'; END IF; current_path = current_path || current_name; RETURN NEXT ( current_parent_hash, current_hash, current_name, current_path, current_type, current_level )::tree_entity; IF current_type = 'tree'::objtype THEN FOR child IN SELECT * FROM git_lookup_tree(current_hash) LOOP SELECT type INTO child_type FROM headers WHERE hash = child.hash; IF child_type IS NULL OR child.name IS NULL THEN CONTINUE; END IF; stack = array_append(stack, ROW ( child.hash, child.name, child_type, current_path, current_hash, current_level + 1 )::tree_stack_entry); END LOOP; END IF; END LOOP; END; $BODY$ LANGUAGE 'plpgsql';