Skip to content

Commit

Permalink
quick save: Fri Dec 27 01:31:15 MSK 2024
Browse files Browse the repository at this point in the history
  • Loading branch information
nikelborm committed Dec 26, 2024
1 parent 8f83e40 commit 0d3f986
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 68 deletions.
6 changes: 2 additions & 4 deletions src/downloadDirectoryContentsMetaInfo.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { octokit } from './octokit.js';
import { Repo } from './repo.interface.js';

export async function downloadDirectoryContentsMetaInfo({
repo,
gitRef,
pathToDirectory
}: {
repo: {
owner: string,
name: string
},
repo: Repo,
pathToDirectory: string,
gitRef: string,
}) {
Expand Down
66 changes: 16 additions & 50 deletions src/downloadDirectoryRecursively.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,24 @@ import { pipeline } from 'node:stream/promises';
import { createGunzip } from 'node:zlib';
import path from 'path';
import tarFs from 'tar-fs';
import { downloadDirectoryContentsMetaInfo } from "./downloadDirectoryContentsMetaInfo.js";
import { getReadableTarGzStreamOfRepoDirectory } from './getReadableTarGzStreamOfRepoDirectory.js';
import { getGitTreeRefFromParentTreeRef } from './getGitTreeRefFromParentTreeRef.js';
import { Repo } from './repo.interface.js';

export async function downloadDirectoryRecursively({
repo,
pathToDirectoryInRepo,
commitShaHashOrBranchNameOrTagName,
pathToLocalDirIntoWhichContentsOfRepoDirWillBePut,
}: {
repo: {
owner: string,
name: string
},
repo: Repo,
pathToDirectoryInRepo: string,
pathToLocalDirIntoWhichContentsOfRepoDirWillBePut: string,
commitShaHashOrBranchNameOrTagName?: string | undefined,
}) {
const directoriesInPath = path
.join(pathToDirectoryInRepo) // cleans up the path of stupid shit
.replace(/\/*$/, '') // remove trailing slash
.join(pathToDirectoryInRepo) // cleans up the path of stupid shit, also removes ./ in the beginning
.replace(/\/*$/, '') // removes trailing slash
.split('/');

// few options generally present in directoriesInPath: [nonEmptyString],
Expand All @@ -31,53 +29,21 @@ export async function downloadDirectoryRecursively({
`Can't go to parent folder like that: ${pathToDirectoryInRepo}`
);

const target =
directoriesInPath['length'] === 1 && directoriesInPath[0] === '.'
? { directoryToDownload: 'root' as const }
: directoriesInPath['length'] === 1
? {
directoryToDownload: 'dirDirectlyInRoot' as const,
directoryName: directoriesInPath[0] as string
}
: directoriesInPath['length'] > 1
? {
directoryToDownload: 'nestedDir' as const,
directoryName: directoriesInPath.at(-1) as string,
pathToParentDirectory: directoriesInPath
.slice(0, -1) // takes everything except last one
.join('/'),
}
: (() => { throw new Error('Impossible directoriesInPath.length === 0') })();

let gitRef = commitShaHashOrBranchNameOrTagName || 'HEAD'

if (target.directoryToDownload !== 'root') {
const pathToDirectory = target.directoryToDownload === 'dirDirectlyInRoot'
? "."
: target.pathToParentDirectory;

const parentDirectoryContentsMetaInfo = await downloadDirectoryContentsMetaInfo({
// '.' can only be there only when that's all there is. Path removes all
// './', so '.' will never be just left. If it's there, it's very
// intentional and no other elements in the path exist.
if (directoriesInPath[0] !== '.') {
const parentDirectoryPathElements = [...directoriesInPath];
const childDirectoryName = parentDirectoryPathElements.pop()!;

gitRef = await getGitTreeRefFromParentTreeRef({
parentDirectoryPath: parentDirectoryPathElements.join('/') || '.',
childDirectoryName,
parentGitRef: gitRef,
repo,
gitRef,
pathToDirectory,
});

const dirElement = parentDirectoryContentsMetaInfo.find(
({ name }) => name === target.directoryName,
);

const fullPathOfDownloadableDirectory = path.join(
pathToDirectory,
target.directoryName
);

if (!dirElement)
throw new Error(`${fullPathOfDownloadableDirectory} does not exist.`);

if (dirElement.type !== 'dir')
throw new Error(`${fullPathOfDownloadableDirectory} is not a directory`);

gitRef = dirElement.sha;
}

await pipeline(
Expand Down
13 changes: 4 additions & 9 deletions src/downloadInfoAboutAllBlobsInDirectory.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import { octokit } from './octokit.js';
import { Repo } from './repo.interface.js';

export async function downloadInfoAboutAllBlobsInDirectory({
repo,
gitTreeShaHashOfDirectory,
}: {
repo: {
owner: string,
name: string
},
export async function downloadInfoAboutAllBlobsInDirectory(
repo: Repo,
gitTreeShaHashOfDirectory: string,
}) {
) {
const { data: { tree: flatTreeOfDirectory } } = await octokit.request(
'GET /repos/{owner}/{repo}/git/trees/{tree_sha}',
{
Expand Down
40 changes: 40 additions & 0 deletions src/getGitTreeRefFromParentTreeRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import path from 'path';
import { downloadDirectoryContentsMetaInfo } from './downloadDirectoryContentsMetaInfo.js';
import { Repo } from './repo.interface.js';

export async function getGitTreeRefFromParentTreeRef({
repo,
parentDirectoryPath,
parentGitRef,
childDirectoryName,
}: {
repo: Repo,
parentDirectoryPath: string,
childDirectoryName: string,
parentGitRef: string,
}) {
const parentDirectoryContentsMetaInfo = await downloadDirectoryContentsMetaInfo({
repo,
gitRef: parentGitRef,
pathToDirectory: parentDirectoryPath,
});

const dirElement = parentDirectoryContentsMetaInfo.find(
({ name }) => name === childDirectoryName,
);

const fullPathOfDownloadableDirectory = path.join(
parentDirectoryPath,
childDirectoryName
);

if (!dirElement)
throw new Error(`${fullPathOfDownloadableDirectory} does not exist.`);

if (dirElement.type !== 'dir')
throw new Error(`${fullPathOfDownloadableDirectory} is not a directory`);

const childTreeRef = dirElement.sha

return childTreeRef;
}
8 changes: 3 additions & 5 deletions src/getReadableTarGzStreamOfRepoDirectory.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { Readable } from 'stream';
import { octokit } from './octokit.js';
import { Repo } from './repo.interface.js';

export async function getReadableTarGzStreamOfRepoDirectory(
repo: {
owner: string,
name: string
},
repo: Repo,
gitRef: string
) {
const { data } = await octokit.request('GET /repos/{owner}/{repo}/tarball/{ref}', {
Expand All @@ -15,7 +13,7 @@ export async function getReadableTarGzStreamOfRepoDirectory(
headers: {
'X-GitHub-Api-Version': '2022-11-28'
}
}) as { data: ArrayBuffer }// tar.gz
}) as { data: ArrayBuffer } // tar.gz

return new Readable({
read() {
Expand Down
4 changes: 4 additions & 0 deletions src/repo.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface Repo {
owner: string,
name: string
}

0 comments on commit 0d3f986

Please sign in to comment.