diff --git a/src/scripts/repositories.js b/src/scripts/repositories.js index caf9d1d..1eac2ca 100644 --- a/src/scripts/repositories.js +++ b/src/scripts/repositories.js @@ -1,27 +1,59 @@ +import { DockerRegistryUIError } from './error.js'; + const getRepositoryName = (split, max) => { let repositoryName = ''; - for (let i = 0; i < max; i++) { + for (let i = 0; i < Math.min(max, split.length - 1); i++) { repositoryName += `${split[i]}/`; } return repositoryName; }; -export const getBranching = - (min = 1, max = 1) => - (repositories) => +const getLatestRepository = (repo, repoName) => { + if (!repo.images) { + return; + } + if (repo.repo === repoName) { + return repo; + } + for (let i = 0; i < repo.images.length; i++) { + const res = getLatestRepository(repo.images[i], repoName); + if (res) { + return res; + } + } + + if (repoName.startsWith(repo.repo)) { + const newRepo = { repo: repoName, images: [] }; + repo.images.push(newRepo); + return newRepo; + } +}; + +export const getBranching = (min = 1, max = 1) => { + if (min > max) { + throw new DockerRegistryUIError(`min must be inferior to max (min: ${min} <= max: ${max})`); + } else if (max < 0 || min < 0) { + throw new DockerRegistryUIError( + `min and max must be greater than equals to 0 (min: ${min} >= 0 and max: ${max} >= 0)` + ); + } + return (repositories) => repositories.sort().reduce(function (acc, image) { const split = image.split('/'); if (split.length > min && min > 0) { const repoName = getRepositoryName(split, max); - if (acc.length === 0 || acc[acc.length - 1].repo != repoName) { - acc.push({ + let repo = acc.length > 0 && getLatestRepository(acc[acc.length - 1], repoName); + if (!repo) { + repo = { repo: repoName, images: [], - }); + }; + acc.push(repo); } - acc[acc.length - 1].images.push(image); + repo.images.push(image); return acc; } acc.push(image); return acc; }, []); +}; diff --git a/test/repositories.test.js b/test/repositories.test.js index d8bc125..4e96e5c 100644 --- a/test/repositories.test.js +++ b/test/repositories.test.js @@ -1,4 +1,5 @@ import { getBranching } from '../src/scripts/repositories.js'; +import { DockerRegistryUIError } from '../src/scripts/error.js'; import assert from 'assert'; describe('repositories', () => { @@ -6,9 +7,10 @@ describe('repositories', () => { it('should not branch for no levels', () => { const branching = getBranching(0, 0); assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']); - assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [ + assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'joxit/docker-registry-ui/amd64', 'nginx']), [ 'alpine', 'joxit/docker-registry-ui', + 'joxit/docker-registry-ui/amd64', 'nginx', ]); }); @@ -21,11 +23,99 @@ describe('repositories', () => { { images: ['joxit/docker-registry-ui'], repo: 'joxit/' }, 'nginx', ]); - assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'joxit/kokai', 'nginx']), [ + assert.deepEqual( + branching(['alpine', 'joxit/docker-registry-ui', 'joxit/kokai', 'joxit/docker-registry-ui/amd64', 'nginx']), + [ + 'alpine', + { images: ['joxit/docker-registry-ui', 'joxit/docker-registry-ui/amd64', 'joxit/kokai'], repo: 'joxit/' }, + 'nginx', + ] + ); + }); + + it('should branch for two level', () => { + const branching = getBranching(2, 2); + assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']); + assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [ + 'alpine', + 'joxit/docker-registry-ui', + 'nginx', + ]); + assert.deepEqual( + branching([ + 'alpine', + 'joxit/docker-registry-ui', + 'joxit/kokai', + 'joxit/docker-registry-ui/amd64', + 'joxit/docker-registry-ui/amd64/latest', + 'joxit/docker-registry-ui/armv7', + 'joxit/docker-registry-ui/armv7/latest', + 'nginx', + ]), + [ + 'alpine', + 'joxit/docker-registry-ui', + { + images: [ + 'joxit/docker-registry-ui/amd64', + 'joxit/docker-registry-ui/amd64/latest', + 'joxit/docker-registry-ui/armv7', + 'joxit/docker-registry-ui/armv7/latest', + ], + repo: 'joxit/docker-registry-ui/', + }, + 'joxit/kokai', + 'nginx', + ] + ); + }); + + it('should branch from one to two level', () => { + const branching = getBranching(1, 2); + assert.deepEqual(branching(['alpine', 'debian', 'nginx']), ['alpine', 'debian', 'nginx']); + assert.deepEqual(branching(['alpine', 'joxit/docker-registry-ui', 'nginx']), [ 'alpine', - { images: ['joxit/docker-registry-ui', 'joxit/kokai'], repo: 'joxit/' }, + { images: ['joxit/docker-registry-ui'], repo: 'joxit/' }, 'nginx', ]); + assert.deepEqual( + branching([ + 'alpine', + 'joxit/docker-registry-ui', + 'joxit/kokai', + 'joxit/docker-registry-ui/amd64', + 'joxit/docker-registry-ui/amd64/latest', + 'joxit/docker-registry-ui/armv7', + 'joxit/docker-registry-ui/armv7/latest', + 'nginx', + ]), + [ + 'alpine', + { + images: [ + 'joxit/docker-registry-ui', + { + images: [ + 'joxit/docker-registry-ui/amd64', + 'joxit/docker-registry-ui/amd64/latest', + 'joxit/docker-registry-ui/armv7', + 'joxit/docker-registry-ui/armv7/latest', + ], + repo: 'joxit/docker-registry-ui/', + }, + 'joxit/kokai', + ], + repo: 'joxit/', + }, + 'nginx', + ] + ); }); }); + + it('should branch from one to two level', () => { + assert.throws(() => getBranching(2, 1), DockerRegistryUIError, `Did not throw on min > max`); + assert.throws(() => getBranching(-2, 1), DockerRegistryUIError, `Did not throw on min < 0`); + assert.throws(() => getBranching(2, -1), DockerRegistryUIError, `Did not throw on max < 0`); + }); });