% If the mip command exists, inform the user and abort. % Note: the syntax '/mip' limits the search to non-builtin functions named mip. if ~isempty(which('/mip')) fprintf('mip is already installed.\n'); fprintf('To update mip, run ''mip update mip''.\n'); fprintf('To uninstall mip, run ''mip uninstall mip''.\n'); return end fprintf('----- Welcome to the mip installation wizard! -----\n\n'); fprintf(['This script will:\n' ... '- Download the latest version of mip.\n' ... '- Install it to a specified directory.\n' ... '- Save mip to your MATLAB path for future sessions.\n']); % Non-interactive installs: the MIP_INSTALL_DIR environment variable, when % set, selects the install location without prompting. Under matlab -batch, % where user input is unavailable, the prompt is also skipped and the % default location is used. mip_install___input = getenv('MIP_INSTALL_DIR'); mip_install___batch = exist('batchStartupOptionUsed', 'builtin') ~= 0 && batchStartupOptionUsed; if isempty(mip_install___input) && ~mip_install___batch % Prompt the user for custom mip location (default: /mip) if ispc || isempty(getenv('HOME')) mip_install___input = input(strrep(sprintf('\nEnter install location for mip (%s): ', fullfile(userpath, 'mip')), '\', '\\'), 's'); else mip_install___input = input(strrep(sprintf('\nEnter install location for mip (%s): ', replace(fullfile(userpath, 'mip'), getenv('HOME'), '~')), '\', '\\'), 's'); end end if isempty(mip_install___input) mip_install___mipdir = fullfile(userpath, 'mip'); else mip_install___mipdir = mip_install___input; end if ispc || isempty(getenv('HOME')) mip_install___mipdirpretty = mip_install___mipdir; else mip_install___mipdirpretty = replace(mip_install___mipdir, getenv('HOME'), '~'); end mip_install___mippackagedir = fullfile(mip_install___mipdir, 'packages', 'gh', 'mip-org', 'core', 'mip'); mip_install___mipsourcedir = fullfile(mip_install___mippackagedir, 'mip'); % If the install directory already exists, adopt the mip that is already there % instead of installing a second copy. Being absent from the path does not mean % mip is not installed: the saved path lives in /toolbox/local/pathdef.m, % which belongs to one MATLAB installation, while mip is installed under the % user's home directory. Installing a new MATLAB release, or running on a % machine whose MATLAB comes and goes (a CI runner with its own MATLAB), leaves % the installation in place with nothing on the path pointing at it. Adopting % means adding it back to the path, which is all a fresh install does once the % files are unpacked. mip_install___adopt = isfolder(mip_install___mipdir); if mip_install___adopt && ~isfile(fullfile(mip_install___mipsourcedir, 'mip.m')) % The directory is in the way but holds no mip to adopt. Refuse rather than % unpacking into it, and rather than putting a directory with no mip.m on % the path (which would fail later as an undefined `mip` function). fprintf('Directory ''%s'' already exists but does not contain a mip installation.\n', mip_install___mipdirpretty); fprintf('Remove it, or set the MIP_INSTALL_DIR environment variable to another location, and try again.\n'); clear mip_install___* error('mip:install:dirExists', ... 'mip install directory already exists but contains no mip installation.'); end if mip_install___adopt % The banner above promised a download. Say plainly that there was none, so % it is clear no second copy was installed over the existing one. fprintf('Found an existing mip installation in ''%s''.\n', mip_install___mipdirpretty); fprintf('Nothing was downloaded; that installation will be used.\n'); end if ~mip_install___adopt % Find all versions of mip available in the package index try mip_install___package_index = webread('https://mip-org.github.io/mip-core/index.json'); catch clear mip_install___* error('Failed to download mip. Installation aborted.'); end mip_install___versions = {}; for mip_install___i = 1:length(mip_install___package_index.packages) if strcmpi(mip_install___package_index.packages{mip_install___i}.name, 'mip') mip_install___versions = [ mip_install___versions ; mip_install___package_index.packages{mip_install___i} ]; %#ok end end if isempty(mip_install___versions) clear mip_install___* error('Failed to download mip. Installation aborted.'); end % Select the best version of mip % Priority: highest numeric version > "main" > "unspecified" > alphabetically first mip_install___latest = []; mip_install___latest_numeric = ''; for mip_install___i = 1:length(mip_install___versions) mip_install___v = mip_install___versions{mip_install___i}.version; mip_install___parts = str2double(strsplit(mip_install___v, '.')); if ~any(isnan(mip_install___parts)) % Numeric version - compare to find highest if isempty(mip_install___latest_numeric) mip_install___latest = mip_install___versions{mip_install___i}; mip_install___latest_numeric = mip_install___v; else mip_install___v1 = mip_install___parts; mip_install___v2 = str2double(strsplit(mip_install___latest_numeric, '.')); mip_install___vmaxlen = max(length(mip_install___v1), length(mip_install___v2)); mip_install___v1(end+1:mip_install___vmaxlen) = 0; mip_install___v2(end+1:mip_install___vmaxlen) = 0; for mip_install___j = 1:mip_install___vmaxlen if mip_install___v1(mip_install___j) > mip_install___v2(mip_install___j) mip_install___latest = mip_install___versions{mip_install___i}; mip_install___latest_numeric = mip_install___v; break elseif mip_install___v1(mip_install___j) < mip_install___v2(mip_install___j) break end end end end end % If no numeric version found, fall back to "main", then "unspecified", then first if isempty(mip_install___latest) for mip_install___i = 1:length(mip_install___versions) if strcmp(mip_install___versions{mip_install___i}.version, 'main') mip_install___latest = mip_install___versions{mip_install___i}; break end end end if isempty(mip_install___latest) for mip_install___i = 1:length(mip_install___versions) if strcmp(mip_install___versions{mip_install___i}.version, 'unspecified') mip_install___latest = mip_install___versions{mip_install___i}; break end end end if isempty(mip_install___latest) mip_install___latest = mip_install___versions{1}; end % Download the .mhl for the latest version of mip from the package index mip_install___mhl = mip_install___latest.mhl_url; if isempty(mip_install___mhl) clear mip_install___* error('Failed to download mip. Installation aborted.'); end fprintf('Installing mip version %s to ''%s''\n', mip_install___latest.version, mip_install___mipdirpretty); % Unzip the .mhl to /packages/gh/mip-org/core/mip try unzip(mip_install___mhl, mip_install___mippackagedir); catch if isfolder(mip_install___mipdir) rmdir(mip_install___mipdir, 's'); end clear mip_install___* error('Failed to download mip. Installation aborted.'); end end % if ~mip_install___adopt % Cache the user's current path mip_install___current_path = path; % Add /packages/gh/mip-org/core/mip/mip to the path and save it for % future MATLAB sessions. savepath() returns a nonzero status (rather than % erroring) when it cannot write pathdef.m -- common on managed or shared % installs where it is read-only. That is not fatal: mip still works in this % session, so warn with manual instructions rather than aborting. mip_install___saved = false; try % Change the path to match what it would be if MATLAB had just started up path(pathdef); addpath(mip_install___mipsourcedir); mip_install___saved = savepath() == 0; catch end % Restore the path to what it was before and add /packages/gh/mip-org/core/mip/mip % to the path for the current MATLAB session (whether or not the save worked) path(mip_install___current_path); addpath(mip_install___mipsourcedir); if mip_install___adopt fprintf('mip is now on your MATLAB path.\n'); fprintf('To update mip, run ''mip update mip''.\n'); else fprintf('Installation successful!\n'); fprintf('Type ''mip help'' to get started.\n'); end if ~mip_install___saved fprintf(['\nWarning: mip could not be saved to your MATLAB path for future sessions.\n' ... 'To load mip automatically in future sessions, add this line to your\n' ... 'startup.m file:\n\n' ... ' addpath(''%s'')\n\n'], ... fullfile(mip_install___mipdirpretty, 'packages', 'gh', 'mip-org', 'core', 'mip', 'mip')); end % Clean up the workspace clear mip_install___*