Mini Kabibi Habibi

Current Path : C:/Program Files/Adobe/Adobe Creative Cloud Experience/js/
Upload File :
Current File : C:/Program Files/Adobe/Adobe Creative Cloud Experience/js/customhook.js

/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * ___________________
 *
 * Copyright 2023 Adobe Inc.
 * All Rights Reserved.
 *
 * NOTICE: All information contained herein is, and remains
 * the property of Adobe Inc. and its suppliers,
 * if any. The intellectual and technical concepts contained
 * herein are proprietary to Adobe Inc. and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Inc..
 **************************************************************************/

console.time('customhook');
const fs = require('fs-extra');
const path = require('path');

const args = process.argv.slice(2);
const AdobeCommonUXPMac = path.resolve('/', 'Library', 'Application Support', 'Adobe/UXP/extensions');
const AdobeCommonUXPWin = path.resolve('C:/', 'Program Files', 'Common Files', 'Adobe/UXP/extensions');
const isMac = process.platform === 'darwin';
const minimumHsBuildMajor = 3;
const minimumHsBuildMinor = 3;
const maximumHsBuildMajor = 8;
// Below directories are not to be deleted as they have manifest min version changes.
let hsUniqueBuildsIntervals = [
    'com.adobe.ccx.start-3.4.2',
    'com.adobe.ccx.start-3.6.0',
    'com.adobe.ccx.start-3.8.1',
    'com.adobe.ccx.start-4.3.1',
    'com.adobe.ccx.start-4.4.0',
    'com.adobe.ccx.start-5.12.2',
    'com.adobe.ccx.start-6.1.0',
    'com.adobe.ccx.start-6.7.0',
    'com.adobe.ccx.start-6.8.0',
    'com.adobe.ccx.start-7.0.0',
    'com.adobe.ccx.start-7.1.0',
    'com.adobe.ccx.start-7.2.1',
    'com.adobe.ccx.start-7.9.1',
];

let hsUniqueBuildsIntervalsFound = new Map();
const directoryPath = isMac ? AdobeCommonUXPMac : AdobeCommonUXPWin;

const regex = /^com\.adobe\.ccx\.start-\d+\.\d+\.\d+$/;

let directoriesToDelete = [];
let directoriesOnMachine = [];
let buildsToKeep = [];

// Function to get the major and minor versions from a directory name
function getVersionParts(directory) {
    const [, major, minor, patch] = directory?.match(/com.adobe.ccx.start-(\d+)\.(\d+).(\d+)/);
    return { major: parseInt(major), minor: parseInt(minor), patch: parseInt(patch) };
}

// Function to iterate to the new interval based on the current build
function iterateToTheNextHsInterval(buildMajor, buildMinor, hsBuildsIntervalsIndex) {
    while (hsBuildsIntervalsIndex < hsUniqueBuildsIntervals.length) {
        const { major: intervalMajor, minor: intervalMinor } = getVersionParts(
            hsUniqueBuildsIntervals[hsBuildsIntervalsIndex],
        );
        const notOverflown = hsBuildsIntervalsIndex < hsUniqueBuildsIntervals.length;
        const buildMajorIsDistinct = intervalMajor !== undefined && buildMajor !== intervalMajor;
        const buildMinorIsBigger = intervalMinor !== undefined && buildMinor > intervalMinor;

        if (notOverflown && (buildMajorIsDistinct || buildMinorIsBigger)) {
            hsBuildsIntervalsIndex++;
        } else {
            break;
        }
    }

    return hsBuildsIntervalsIndex;
}

// Iterate between all of the builds and find the ones to keep
findTheBuildsToKeep = () => {
    let userBuildsArrayIndex = 0;
    let lastValidBuild;
    const { major, minor } = getVersionParts(directoriesOnMachine?.[0]);
    let hsBuildsIntervalsIndex = iterateToTheNextHsInterval(major, minor, 0);

    while (userBuildsArrayIndex < directoriesOnMachine.length) {
        const currentBuild = directoriesOnMachine[userBuildsArrayIndex];
        const currentInterval = hsUniqueBuildsIntervals[hsBuildsIntervalsIndex];
        const { major: currentBuildMajor, minor: currentBuildMinor } = getVersionParts(currentBuild);
        const { major: currentIntervalEndMajor, minor: currentIntervalEndMinor } = getVersionParts(currentInterval);

        if (hsUniqueBuildsIntervals.includes(currentBuild)) {
            buildsToKeep.push(currentBuild);
            hsUniqueBuildsIntervalsFound.set(currentBuild, true);

            if (lastValidBuild && !hsUniqueBuildsIntervalsFound.get(currentInterval)) {
                buildsToKeep.push(lastValidBuild);
                hsUniqueBuildsIntervalsFound.set(currentInterval, true);
            }

            lastValidBuild = null;
            hsBuildsIntervalsIndex = iterateToTheNextHsInterval(
                currentBuildMajor,
                currentBuildMinor,
                hsBuildsIntervalsIndex,
            );
        } else if (currentBuildMajor === currentIntervalEndMajor && currentBuildMinor <= currentIntervalEndMinor) {
            lastValidBuild = currentBuild;
        } else {
            if (lastValidBuild) {
                buildsToKeep.push(lastValidBuild);
                hsUniqueBuildsIntervalsFound.set(currentInterval, true);
            }
            lastValidBuild = currentBuild;
            hsBuildsIntervalsIndex = iterateToTheNextHsInterval(
                currentBuildMajor,
                currentBuildMinor,
                hsBuildsIntervalsIndex,
            );
        }
        userBuildsArrayIndex++;
    }

    if (lastValidBuild) {
        buildsToKeep.push(lastValidBuild);
    }
};

// Thor deletes the cwd after calling this script. Therefore it crashes on mac
// as we do not have a valid working directory.
process.chdir(__dirname);
if (args.includes('removehs')) {
    try {
        // Read the list of directories
        fs.readdir(directoryPath, (err, directories) => {
            if (err) throw err;

            directories.forEach(directory => {
                // Populate a list of directories present on user machine.
                // Condition to check if HS extension is directory and is in expected format
                if (fs.statSync(directoryPath + '/' + directory).isDirectory() && regex.test(directory)) {
                    const { major, minor } = getVersionParts(directory);
                    // Keep all the versions less that 3.3 safe, we add it to directoriesToKeep list.
                    if (
                        major < minimumHsBuildMajor ||
                        (major === minimumHsBuildMajor && minor <= minimumHsBuildMinor) ||
                        major >= maximumHsBuildMajor
                    ) {
                        buildsToKeep.push(directory);
                    } else {
                        directoriesOnMachine.push(directory);
                    }
                }
            });

            if (directoriesOnMachine.length === 0) {
                console.log('No valid directories found on user machine');
                return;
            }

            directoriesOnMachine.sort((a, b) => {
                const { major: aMajor, minor: aMinor, patch: aPatch } = getVersionParts(a);
                const { major: bMajor, minor: bMinor, patch: bPatch } = getVersionParts(b);

                if (aMajor !== bMajor) {
                    return aMajor - bMajor;
                } else if (aMinor !== bMinor) {
                    return aMinor - bMinor;
                } else {
                    return aPatch - bPatch;
                }
            });

            findTheBuildsToKeep();

            console.log('directories on user machine', directoriesOnMachine);
            console.log('builds to keep', buildsToKeep);
            // Get a list of directories which are present on user machine but not present on directories to keep list.
            directoriesToDelete = directoriesOnMachine.filter(item => !buildsToKeep.includes(item));
            console.log('directories to delete', directoriesToDelete);
            // Delete directories that are not the highest minor version for their respective major version and also directories not present in directories to keep list.
            directoriesToDelete.forEach(directory => {
                fs.remove(directoryPath + '/' + directory, err => {
                    if (err) {
                        console.log(`Error deleting ${directory} - ${err}`);
                        return;
                    }
                    console.log(`Deleted: ${directory}`);
                });
            });
        });
        console.timeEnd('customhook');
    } catch (error) {
        console.log(`Failed to execute customhook script ${error}`);
    }
}