diff --git a/.gitignore b/.gitignore index 2c3de20..f55bc30 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ slprj/ # Session info octave-workspace + +package.json \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c5eeefe --- /dev/null +++ b/.travis.yml @@ -0,0 +1,170 @@ +os: linux +dist: xenial +language: general + +############################################################################### +cache: + # Downloading octave takes a while, so let's cache apt + apt: true + directories: + # Cache octave packages + - $HOME/octave + # Cache other packages + - $HOME/external_cache + +############################################################################### +env: + jobs: + - COVERAGE="false" + - COVERAGE="true" + jobs: + allow_failures: '[{ env: COVERAGE=true }]' + fast_finish: true + +############################################################################### +# Command to install dependencies +before_install: + - echo '' > build.xml + # Remember the directory where our repository to test is located + - REPOPATH="$(pwd)" && pwd + # --------------------------------------------------------------------------- + # Check whether we need to upgrade the gcc and g++ versions. We do need to if + # the version is less the 4.8 and we need to install the image package from + # Octave Forge (possibly for other packages as well). + # For now, lets just always say we do need to do this. + - UPGRADE_GCC="true" + # --------------------------------------------------------------------------- + # Add repository for octave + - travis_retry sudo add-apt-repository -y ppa:octave/stable + # Add repository for installing g++-4.8 on Ubuntu 12.04 + - if [ "$UPGRADE_GCC" = "true" ]; then + sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; + fi + # Update apt-get to include the contents from the new locations + - travis_retry sudo apt-get update -qq + # Install octave with apt-get + - travis_retry sudo apt-get install -y octave liboctave-dev + # Add a C++11 compiler so we can install image package + - if [ "$UPGRADE_GCC" = "true" ]; then + travis_retry sudo apt-get install -y gcc-4.8 g++-4.8; + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50; + sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50; + fi; + # Check which versions of g++ and gcc we are using + - which g++; + g++ --version; + which gcc; + gcc --version; + # --------------------------------------------------------------------------- + # Go up one level and retrieve MOxUnit from its repository + - cd ..; + ls -alh; + # Remove directory if it is already there from previous build + - rm -rf MOxUnit; + - git clone https://github.com/MOxUnit/MOxUnit.git + # Install MOxUnit, which adds itself to the startup path + - make -C MOxUnit install + # Install MOcov, which adds itself to the startup path + - if [ "$COVERAGE" = "true" ]; then + rm -rf MOcov; + git clone https://github.com/MOcov/MOcov.git; + make -C MOcov install; + fi; + # Go back to the repository directory + - cd ${REPOPATH} + +############################################################################### +install: + # Ensure external packages folder exists and is empty + - EXTPATH="source/external"; + echo ${EXTPATH}; + rm -rf ${EXTPATH}; + mkdir -p ${EXTPATH}; + # Install required packages for Octave + - if [ -f requirements-octave.txt ]; then + mopi/mopi.sh requirements-octave.txt ${EXTPATH} "$HOME/external_cache"; + fi; + # Install other required packages + - if [ -f requirements.txt ]; then + mopi/mopi.sh requirements.txt ${EXTPATH} "$HOME/external_cache"; + fi; + # Install developmental requirements + - if [ -f requirements-dev.txt ]; then + mopi/mopi.sh requirements-dev.txt ${EXTPATH} "$HOME/external_cache"; + fi; + # Before running the tests, we will have to add our package and our + # external dependencies to the octave path + - PACKAGE_FOLDER="source"; + ADDPATH_COMMAND="addpath(genpath(fullfile(pwd, '$PACKAGE_FOLDER')));"; + ADDPATH_COMMAND+=" addpath(genpath(fullfile(pwd, '${EXTPATH}')));"; + echo "ADDPATH_COMMAND| $ADDPATH_COMMAND"; + +############################################################################### +before_script: + - testFolder="source/tests" + - TEST_ARGS="'-recursive', '-verbose', '-junit_xml_file', 'testresults.xml'"; + if [ "$COVERAGE" = "true" ]; then + TEST_ARGS+=", '-with_coverage', '-cover', '$PACKAGE_FOLDER'"; + TEST_ARGS+=", '-cover_exclude', ${testFolder}"; + TEST_ARGS+=", '-cover_xml_file', 'coverage.xml'"; + TEST_ARGS+=", '-cover_json_file', 'coveralls.json'"; + fi; + TEST_COMMAND="exit(~moxunit_runtests('${testFolder}', $TEST_ARGS));"; + echo "TEST_COMMAND| $TEST_COMMAND"; + # Double-check we are still in the right directory + - pwd + # Check what octave packages we have installed + # - octave -q --eval "ver" + # - octave -q --eval "2+3" + # --------------------------------------------------------------------------- + # Remove any cached results files from previous build, if present + - rm -f testresults.xml; + rm -f coverage.xml; + rm -f .coverage; + rm -f coveralls.json; + # --------------------------------------------------------------------------- + # Set up folders for test results on Shippable + - if [ "$SHIPPABLE" = "true" ]; then + rm -fr shippable; + mkdir -p shippable/testresults; + mkdir -p shippable/codecoverage; + fi; +############################################################################### +script: + - octave -v --eval "moxunit_runtests('${testFolder}')" + # - octave -v --eval "$ADDPATH_COMMAND $TEST_COMMAND"; + +############################################################################### +after_script: + # Check where we ended up and what's going on where we are + - pwd + - ls -alh + # --------------------------------------------------------------------------- + # Move results and coverage files into appropriate places + - if [ "$SHIPPABLE" = "true" ] && [ -f testresults.xml ]; then + mv testresults.xml shippable/testresults/; + fi; + if [ "$SHIPPABLE" = "true" ] && [ -f coverage.xml ]; then + cp coverage.xml shippable/codecoverage/; + fi; + +############################################################################### +after_success: + # Only run coveralls on Travis. When running on a public Travis-CI, the + # repo token is automatically inferred, but to run coveralls on Shippable + # the repo token needs to be specified in a .coveralls.yml or as an + # environment variable COVERALLS_REPO_TOKEN. This should be kept hidden + # from public viewing, either by encrypting the token or running on a + # private build. + # We ignore coverage push failures because the servers are not 100% + # reliable and we don't want the CI to report a failure just because the + # coverage report wasn't published. + # For Codecov, we use this https://github.com/codecov/codecov-bash + - if [ "$COVERAGE" = "true" ] && [ "$TRAVIS" = "true" ] && [ "$SHIPPABLE" != "true" ]; then + curl --verbose -F json_file=`pwd`/coveralls.json https://coveralls.io/api/v1/jobs || echo "Coveralls push failed"; + bash <(curl -s https://codecov.io/bash) || echo "Codecov push failed"; + fi; + +############################################################################### +# Enable archiving of artifacts on Shippable (does nothing on Travis) +archive: true diff --git a/README.md b/README.md index ca4a6f1..547981e 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,57 @@ # PackMan -PackMan aims to bring dependency management, similar to what [npm](https://www.npmjs.com) does for [Node.js](https://nodejs.org), to [MATLAB](https://www.mathworks.com/products/matlab.html). It is a fork of and improves on [DepMat](https://github.com/tomdoel/depmat). -# Usage guide +## Table of Contents + +1. [Acknowledgements](#acknowledgements) +2. [Description](#description) +3. [Usage Guide](#usage-guide) +4. [Examples](#examples) +5. [Test](#test) +6. [ToDo](#todo) +7. [Limitations](#limitations) +8. [References](#references) + +## Acknowledgements + +- This PackMan was forked from [OmidS's Packman](https://github.com/OmidS/PackMan). +- OmidS's Packman was forked from a great repository called [DepMat](https://github.com/tomdoel/depmat), by [Tom Doel](http://www.tomdoel.com). + +## Description + +PackMan aims to bring dependency management, similar to what [npm](https://www.npmjs.com) does for [Node.js](https://nodejs.org), to [MATLAB](https://www.mathworks.com/products/matlab.html). It is a fork of and improves on [OmidS's Packman](https://github.com/OmidS/PackMan). + +### Additional Features + +- Adds the possibility to source from private repositories. +- Adds the possibility to write git native commands directly from matlab. + +## Usage guide + Let's say you have a MATLAB project and you want to be able to use external packages in your code. An external package can be any git repository for which you have read access (e.g. any public repository on GitHub). -## One time setup +### One time setup + You will need to do the following once, to enable package management with PackMan for your project: + - Make sure there is no directory called 'external' at the root directory of your project -- Copy "[installDeps.m](https://github.com/OmidS/PackMan/blob/master/source/installDeps.m)" to the root directory of your project -- (Optional) Copy "[getDepList.m](https://github.com/OmidS/PackMan/blob/master/source/getDepList.m)" to the root directory of your project. +- Copy "[installDeps.m](https://raw.githubusercontent.com/DanielAtKrypton/PackMan/master/source/installDeps.m)" to the root directory of your project +- Copy "[getDepList.m](https://raw.githubusercontent.com/DanielAtKrypton/PackMan/master/source/getDepList.m)" to the root directory of your project. Done! Your project is now equipped with dependency management. -## Add/remove dependencies +### Add/remove dependencies + You will need to do the following any time you want to add/remove a dependency + - (Option 1) Update the list of dependencies in a file called package.json (for R2016b and later). PackMan will create a package.json file the first time you call "installDeps.m". Each dependency can have the fields listed in the following sample "package.json": -``` + +```json { "dependencies":{ "PackMan":{ "Name":"PackMan", "Branch":"master", - "Url":"https://github.com/OmidS/PackMan.git", + "Url":"https://github.com/DanielAtKrypton/PackMan.git", "FolderName":"PackMan", "Commit":"", "GetLatest":true @@ -34,31 +64,52 @@ You will need to do the following any time you want to add/remove a dependency Note: when removing any repositories, it is best to delete the 'external' directory completely so that PackMan starts fresh. -## Install/update dependencies +### Install/update dependencies + You will need to do the following to install or update dependencies + - Run the following command (this will install/update all dependencies) -``` + +```matlab >> installDeps; ``` +### Add dependencies to the path + +You will need to run the following to add the dependencies to the MATLAB path before running your code -## Add dependencies to the path -You will need to run the following to add the dependencies to the MATALAB path before running your code - Now before running you code, add dependencies to the path by calling: -``` + +```matlab >> pm = installDeps; ->> addpath(pm.genPath()); +>> addpath(pm.genPath(:)); ``` You can also gracefully remove all dependencies from the path by calling: + +```matlab +>> rmpath(pm.genPath(:)); ``` ->> rmpath(pm.genPath()); + +## Examples + +- [PackManRecursiveSample](https://github.com/DanielAtKrypton/PackManRecursiveSample.git) + +## Test + +```matlab +testsResults = runtests('testPackMan') ``` -## Complete example: -See the following sample repository for a complete usage example for PackMan: -https://github.com/OmidS/matlabPackManSample +## ToDo + +- Add and successfully pass continuous integration. +- Make sure it works for Mac and Linux operating systems. + +## Limitations + +- It was tested for Windows only because git.m uses a batch file workaround (RunCommand.cmd) to allow private repositories to be used within Packman. +## References -# Credits -PackMan was forked from a great repository called [DepMat](https://github.com/tomdoel/depmat), by [Tom Doel](http://www.tomdoel.com). +- [matlab-continuous-integration](https://github.com/scottclowe/matlab-continuous-integration) diff --git a/package.json b/package.json deleted file mode 100644 index 8a21d80..0000000 --- a/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies":{ - - } -} \ No newline at end of file diff --git a/source/DepMat.m b/source/DepMat.m index c22c48a..46894ae 100644 --- a/source/DepMat.m +++ b/source/DepMat.m @@ -84,16 +84,19 @@ function setDispHandler(obj, funcHandle) [return_value, output] = system(command); success = return_value == 0; if ~success - if strfind(output, 'Protocol https not supported or disabled in libcurl') + if contains(output, 'Protocol https not supported or disabled in libcurl') obj.dispHandler('! You need to modify the the DYLD_LIBRARY_PATH environment variable to point to a newer version of libcurl. The version installed with Matlab does not support using https with git.'); end end end function installed = isGitInstalled - command = 'git --help'; - - installed = DepMat.execute(command); + installed = true; + try + git('--help'); + catch + installed = false; + end end function fixCurlPath diff --git a/source/DepMatAddPaths.m b/source/DepMatAddPaths.m index f6be447..1eba46a 100644 --- a/source/DepMatAddPaths.m +++ b/source/DepMatAddPaths.m @@ -21,7 +21,7 @@ function DepMatAddPaths(baseFolderList, repoNameList, forceUpdate) full_path = mfilename('fullpath'); [path_root, ~, ~] = fileparts(full_path); - myPaths = genpath(path_root); + myPaths = genNonGitPath(path_root); allPathsToAdd = [allPathsToAdd, myPaths]; for repoIndex = 1 : numel(baseFolderList) @@ -32,7 +32,7 @@ function DepMatAddPaths(baseFolderList, repoNameList, forceUpdate) DepMat_PathsHaveBeenSet{end + 1} = repoName; end if doAddPaths - repoPaths = genpath(baseFolderList{repoIndex}); + repoPaths = genNonGitPath(baseFolderList{repoIndex}); allPathsToAdd = [allPathsToAdd, repoPaths]; end diff --git a/source/DepMatRepositoryUpdater.m b/source/DepMatRepositoryUpdater.m index 9a1440b..ec6f5ad 100644 --- a/source/DepMatRepositoryUpdater.m +++ b/source/DepMatRepositoryUpdater.m @@ -45,7 +45,7 @@ [status, varargout{1}] = obj.internalGetStatus; if isempty(varargout{1}), [~, varargout{1}] = obj.internalGetHeadHash(); end cd(lastDir); - catch ex + catch cd(lastDir); status = DepMatStatus.GitFailure; end @@ -64,7 +64,7 @@ cd(obj.SourceDir); success = obj.internalCloneRepo; cd(lastDir); - catch ex + catch cd(lastDir); success = false; end @@ -78,7 +78,7 @@ try cd(obj.SourceDir); [success, output] = obj.internalUpdateRepo; - catch ME + catch success = false; output = ''; end @@ -93,7 +93,7 @@ try status = obj.getStatus; - catch ex + catch success = false; obj.dispHandler(['! ' obj.RepoDef.Name ' unable to check for updates']); return; @@ -160,7 +160,7 @@ obj.dispHandler(['! ' obj.RepoDef.Name ' could not check out specified commit (',obj.RepoDef.Commit,')']); end cd(lastDir); - catch ex + catch cd(lastDir); success = false; end @@ -195,18 +195,15 @@ function setDispHandler(obj, funcHandle) return; end - [success, local_id] = DepMat.execute('git remote update'); - if ~success + try + git('remote update'); + local_id_head = git('rev-parse @{0}'); % current head commit + catch status = DepMatStatus.GitFailure; return; end - [success, local_id_head] = DepMat.execute(['git rev-parse @{0}']); % current head commit - if ~success - status = DepMatStatus.GitFailure; - return; - end - local_id_head = strrep(local_id_head,sprintf('\n'),''); + local_id_head = strrep(local_id_head,newline,''); if ~obj.RepoDef.GetLatest if strcmp(local_id_head, obj.RepoDef.Commit) @@ -215,25 +212,18 @@ function setDispHandler(obj, funcHandle) status = DepMatStatus.UpToDateButWrongHead; end else % Get the latest commit - [success, local_id] = DepMat.execute(['git rev-parse ',obj.RepoDef.Branch,'@{0}']); % Latest local commit - if ~success - status = DepMatStatus.GitFailure; - return; - end - [success, remote_id] = DepMat.execute(['git rev-parse ',obj.RepoDef.Branch,'@{u}']); % Latest remote commit - if ~success - status = DepMatStatus.GitFailure; - return; - end - [success, base] = DepMat.execute(['git merge-base ',obj.RepoDef.Branch,'@{0} ',obj.RepoDef.Branch,'@{u}']); - if ~success + try + local_id = git(['rev-parse ',obj.RepoDef.Branch,'@{0}']); % Latest local commit + remote_id = git(['rev-parse ',obj.RepoDef.Branch,'@{u}']); % Latest remote commit + base = git(['merge-base ',obj.RepoDef.Branch,'@{0} ',obj.RepoDef.Branch,'@{u}']); + catch status = DepMatStatus.GitFailure; return; end - local_id = strrep(local_id,sprintf('\n'),''); - remote_id = strrep(remote_id,sprintf('\n'),''); - base = strrep(base,sprintf('\n'),''); + local_id = strrep(local_id,newline,''); + remote_id = strrep(remote_id,newline,''); + base = strrep(base,newline,''); if strcmp(local_id, remote_id) if (~obj.RepoDef.GetLatest && strcmp(obj.RepoDef.Commit, local_id_head) ) || ... @@ -253,25 +243,14 @@ function setDispHandler(obj, funcHandle) end end - function [status, commitHash] = internalGetHeadHash(obj) - status = true; - [success, commitHash] = DepMat.execute('git rev-parse HEAD'); - if ~success - status = DepMatStatus.GitFailure; - return; - end - commitHash = strrep(commitHash,sprintf('\n'),''); - end - function [success, output] = internalUpdateRepo(obj) - [success, output] = DepMat.execute(['git checkout ',obj.RepoDef.Branch]); % Checkout the branch - if ~success - status = DepMatStatus.GitFailure; - return; + try + output = git(['checkout ', obj.RepoDef.Branch]); % Checkout the branch + output = git('pull'); + success = true; + catch + success = false; end - - [pullResult, output] = DepMat.execute('git pull'); - success = ~isempty(pullResult) && ~isequal(pullResult, 0); end function success = internalCloneRepo(obj) @@ -279,31 +258,32 @@ function setDispHandler(obj, funcHandle) % Avoid initialisation if it has already been done, to avoid errors fetchFailure = obj.checkForFetchFailure; if ~fetchFailure - if ~DepMat.execute('git init') - success = false; - return; - end - - if ~DepMat.execute(['git remote add -t ' obj.RepoDef.Branch ' origin ' obj.RepoDef.Url]) + try + git('init'); + git(['remote add -t ' obj.RepoDef.Branch ' origin ' obj.RepoDef.Url]); + catch success = false; return; end end - if ~DepMat.execute('git fetch') + try + git('fetch'); + catch obj.setFetchFailure; - success = false; - return; + return; end - + if ~isempty(obj.RepoDef.Commit)&&~obj.RepoDef.GetLatest - checkoutCmd = ['git checkout ' obj.RepoDef.Commit]; + checkoutCmd = ['checkout ' obj.RepoDef.Commit]; else - checkoutCmd = ['git checkout ' obj.RepoDef.Branch]; + checkoutCmd = ['checkout ' obj.RepoDef.Branch]; end - if ~DepMat.execute(checkoutCmd) + try + git(checkoutCmd); + catch success = false; return; end @@ -316,32 +296,29 @@ function setDispHandler(obj, funcHandle) end function [success, changed, headCommitId] = internalCheckoutCommit(obj) - [success, local_id_head] = DepMat.execute(['git rev-parse @{0}']); % current head commit - local_id_head = strrep(local_id_head,sprintf('\n'),''); - [success, local_id_latest] = DepMat.execute(['git rev-parse ',obj.RepoDef.Branch,'@{0}']); % Latest local commit - local_id_latest = strrep(local_id_latest,sprintf('\n'),''); - - headCommitId = local_id_head; changed = false; - toCheckoutHash = ''; - if ( obj.RepoDef.GetLatest) && ~strcmp(local_id_head, local_id_latest) - toCheckoutHash = local_id_latest; - elseif ~( obj.RepoDef.GetLatest ) && ~strcmp(local_id_head, obj.RepoDef.Commit) - toCheckoutHash = obj.RepoDef.Commit; - end - if ~isempty(toCheckoutHash) - if ~DepMat.execute(['git checkout ' toCheckoutHash]) - success = false; - % changed = true; - return; + try + local_id_head = git('rev-parse @{0}'); % current head commit + local_id_head = strrep(local_id_head,newline,''); + local_id_latest = git(['rev-parse ',obj.RepoDef.Branch,'@{0}']); % Latest local commit + local_id_latest = strrep(local_id_latest,newline,''); + headCommitId = local_id_head; + toCheckoutHash = ''; + if ( obj.RepoDef.GetLatest) && ~strcmp(local_id_head, local_id_latest) + toCheckoutHash = local_id_latest; + elseif ~( obj.RepoDef.GetLatest ) && ~strcmp(local_id_head, obj.RepoDef.Commit) + toCheckoutHash = obj.RepoDef.Commit; end - changed = true; - headCommitId = toCheckoutHash; + if ~isempty(toCheckoutHash) + git(['checkout ' toCheckoutHash]) + changed = true; + headCommitId = toCheckoutHash; + end + success = true; + catch + success = false; + return; end - success = true; - end - - function getHeadCommitId() end function setFetchFailure(obj) @@ -361,5 +338,20 @@ function clearFetchFailure(obj) end end + methods(Static) + function getHeadCommitId + end + + function [status, commitHash] = internalGetHeadHash + status = true; + try + commitHash = git('rev-parse HEAD'); + catch + status = DepMatStatus.GitFailure; + return; + end + commitHash = strrep(commitHash,newline,''); + end + end end diff --git a/source/PackMan.m b/source/PackMan.m index 6fdd11b..16fb766 100644 --- a/source/PackMan.m +++ b/source/PackMan.m @@ -30,7 +30,21 @@ if nargin < 4 || isempty(parDir), parDir = pwd; end obj.parentDir = parDir; - if nargin < 1 || isempty(depList), depList = DepMat.empty; end + if nargin < 1 || isempty(depList) + depList = DepMat.empty; + else + depListLenght = length(depList); + f_names = fieldnames(depList); + f_namesLength = length(f_names); + + constructorParams = cell(f_namesLength, depListLenght); + depObjList = repmat(DepMatRepo(),1,depListLenght); + for i = 1:depListLenght + constructorParams(:, i) = cellfun(@(x)(depList(i).(x)),f_names,'UniformOutput',false); + depObjList(i) = DepMatRepo(constructorParams{:,i}); + end + depList = depObjList; + end if nargin < 2 || isempty(depDirPath), depDirPath = fullfile(obj.parentDir, '/external'); end if nargin < 3 || isempty(packageFilePath) if exist('jsonencode', 'builtin') @@ -116,10 +130,12 @@ function install(obj, alreadyInstalled, depth) if nargin < 2, alreadyInstalled = []; end if nargin < 3, depth = 0; end - for i = 1:length(obj.depList) - if i == 1 - obj.dispHandler(sprintf('Installing dependencies for %s...', obj.parentDir)); - end + depListLength = length(obj.depList); + if depListLength > 0 + obj.dispHandler(sprintf('Installing dependencies for %s...', obj.parentDir)); + end + + for i = 1:depListLength thisDep = obj.depList(i); if ~isempty(alreadyInstalled) && ( ... ismember(thisDep, alreadyInstalled) || ... @@ -131,7 +147,8 @@ function install(obj, alreadyInstalled, depth) for j = 1:length(alreadyInstalled) if (isequal(thisDep.Url, alreadyInstalled(j).Url) || ... isequal(strrep(thisDep.Url, '.git', ''), strrep(alreadyInstalled(j).Url, '.git', ''))) && ... - ~isequal(thisDep.Commit, alreadyInstalled(j).Commit) + isequal(thisDep.Commit, alreadyInstalled(j).Commit) && ... + isequal(thisDep.FolderName, alreadyInstalled(j).FolderName) conflict = true; end end @@ -201,25 +218,27 @@ function recurse( obj, alreadyInstalled, depth ) % pm.install(); % paths = pm.genPath(); % addpath(paths); - if nargin < 2, alreadyAdded = []; end + if nargin < 2, alreadyAdded = {}; end if nargin < 3, selfPaths = true; end - paths = []; + paths = {}; if selfPaths % Add subpaths of this package - paths = [paths, obj.getSelfPaths()]; + paths = [paths; obj.getSelfPaths()]; end % Add parent paths of deps [depSelfPaths, alreadyAdded, nowAdded ] = obj.getDepSelfPaths( alreadyAdded ); - paths = [paths, depSelfPaths]; + paths = [paths; depSelfPaths]; % Recurse to deps of the added deps for di = 1:length(nowAdded) thisDep = nowAdded(di); pm = obj.createDepPackMan( thisDep ); [depPaths, alreadyAdded] = pm.genPath( alreadyAdded, false ); - paths = [paths, depPaths]; + paths = [paths; depPaths]; end + paths = unique(paths); + paths = paths(~endsWith(paths, '\private')); % Private directories not allowed in MATLAB path. if nargout > 1, varargout{1} = alreadyAdded; end end @@ -238,10 +257,10 @@ function recurse( obj, alreadyInstalled, depth ) % Usage sample: % pm.getDepSelfPaths(); - if nargin < 2, alreadyAdded = []; end + if nargin < 2, alreadyAdded = {}; end - nowAdded = []; - paths = ''; + nowAdded = {}; + paths = {}; for di = 1:length( obj.depList ) thisDep = obj.depList(di); % obj.dispHandler(sprintf('Considering dep %s (%s)', thisDep.Name, thisDep.Commit)); @@ -261,7 +280,7 @@ function recurse( obj, alreadyInstalled, depth ) alreadyAdded = cat(1, alreadyAdded, thisDep); nowAdded = cat(1, nowAdded, thisDep); depPaths = pm.getSelfPaths(); - paths = [paths, depPaths]; + paths = [paths; depPaths]; else warning('PackMan:genpath:versionConflict', 'Two different versions of %s were listed as dependencies! Aborted adding of the following version to the path: (%s, located in "%s")!\n', thisDep.Url, thisDep.getVersionStr(), pm.parentDir); end @@ -272,7 +291,7 @@ function recurse( obj, alreadyInstalled, depth ) end function paths = getSelfPaths(obj) - paths = []; + paths = {}; % Add subpaths of this package files = dir(obj.parentDir); files(~[files.isdir]) = []; @@ -280,14 +299,32 @@ function recurse( obj, alreadyInstalled, depth ) for fi = 1:length(files) subDirPath = fullfile(files(fi).folder, files(fi).name); if strcmp(subDirPath, obj.depDirPath), continue; end - paths = [paths, genpath(subDirPath)]; + paths = [paths; genNonGitPath(subDirPath)]; end - paths = [paths, obj.parentDir, ';']; + paths = [{obj.parentDir}; paths]; end function pm = createDepPackMan( obj, dep ) depDir = fullfile(obj.depDirPath, dep.FolderName); pm = PackMan([], '', '', depDir); + + if (~strcmp(dep.Name,'PackMan')) + generatedPath = pm.genPath; + if (all(cellfun(@exist, generatedPath)== 7)) + oldPath = path; + addpath(generatedPath{:}); + s = which('installDeps.m', '-ALL'); + pathIndexesContainintDepDir = contains(s, depDir); + if any(pathIndexesContainintDepDir) + installDepsPath = s{pathIndexesContainintDepDir}; + dpDirPth = fileparts(strrep(installDepsPath,depDir,'')); + getDepListFunction = fullfile(depDir, dpDirPth, 'getDepList.m'); + run(getDepListFunction); + pm = PackMan(ans, fullfile(fileparts(installDepsPath),'external') , '', depDir); + end + path(oldPath); + end + end end function saveToFile(obj) @@ -536,5 +573,4 @@ function setDispHandler(obj, funcHandle) if ind < length(str), strO = sprintf('%s%s', strO, str((ind+1):end)); end end end -end - +end \ No newline at end of file diff --git a/source/RunCommand.cmd b/source/RunCommand.cmd new file mode 100644 index 0000000..092a080 --- /dev/null +++ b/source/RunCommand.cmd @@ -0,0 +1,10 @@ +@echo off + +for /f "tokens=1,* delims= " %%a in ("%*") do set ALL_BUT_FIRST=%%b +SET cmdToRun=%ALL_BUT_FIRST% + +echo Executing git command on %~1 repository: %cmdToRun% + +(%cmdToRun%) > %~1CommandOutput + +exit \ No newline at end of file diff --git a/source/genNonGitPath.m b/source/genNonGitPath.m new file mode 100644 index 0000000..8105979 --- /dev/null +++ b/source/genNonGitPath.m @@ -0,0 +1,11 @@ +function pathList = genNonGitPath(folderName) +%genPath - Description +% +% Syntax: output = genPath(input) +% +% Long description + +paths = genpath(folderName); +pathList = split(paths, ';'); +pathList = rmmissing(pathList); +pathList = pathList(~contains(pathList, '\.git')); \ No newline at end of file diff --git a/source/getDepList.m b/source/getDepList.m index fcb6151..e2ff7ff 100644 --- a/source/getDepList.m +++ b/source/getDepList.m @@ -4,10 +4,12 @@ function depList = getDepList -depList = []; +depList = {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; +depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); % Arguments for DepMatRepo: DepMatRepo(Name, Branch, Url, FolderName, Commit, GetLatest) -% Example: -% depList = DepMatRepo('PackMan', 'master', 'https://github.com/OmidS/PackMan.git', 'PackMan', '', true); -% depList(end+1, 1) = DepMatRepo('depmat', 'master', 'https://github.com/OmidS/depmat.git', 'subid', '', true); - -end \ No newline at end of file +% Example: +% depList = [... +% {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; +% {'DataHash', 'master', 'https://github.com/DanielAtKrypton/DataHash.git', 'DataHash', '', true}; +% ]; +% depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); \ No newline at end of file diff --git a/source/git.m b/source/git.m new file mode 100644 index 0000000..6680bca --- /dev/null +++ b/source/git.m @@ -0,0 +1,73 @@ +function [result, status] = git(varargin) + %GIT Summary of this function goes here + % Detailed explanation goes here + if (nargin == 0) + ME = MException('Packman:gitError', ... + 'Not enough input args'); + throw(ME); + end + splitCells = cellfun(@split, varargin, 'UniformOutput', false); + parametersList = vertcat(splitCells{:}); + firstParameter = parametersList{1}; + gitPlusParametersList = [{'git'}, parametersList{:}]; + spaceSeparatedGitPlusParametersList = join(gitPlusParametersList, ' '); + commandString = spaceSeparatedGitPlusParametersList{1}; + switch firstParameter + case 'remote' + case 'pull' + case 'fetch' + case 'push' + otherwise + [status, result] = system(commandString); + if status + ME = MException('Git:couldntExecuteGitCommand', ... + 'git command %s resulted in a failure!', commandString); + throw(ME); + end + return; + end + name = getRepoName(); + filename = [name 'CommandOutput']; + fid = fopen(filename , 'wt' ); + fclose(fid); + + [status, ~] = dos([which('RunCommand.bat') ' ' name ' ' commandString ' &']); + if status + ME = MException('Git:couldntExecuteGitCommand', ... + 'git command %s resulted in failure!', commandString); + throw(ME); + end + v = ver; + isRoboticsToolboxAvailable = any(strcmp('Robotics System Toolbox', {v.Name})); + desiredRate = 20; + if (isRoboticsToolboxAvailable) + r = robotics.Rate(desiredRate); + reset(r); + end + while(true) + fid = fopen(filename, 'rt' ); + contents = textscan(fid,'%s','Delimiter','\n'); + contents = contents{1}; + fclose(fid); + if ~isempty(contents) + delete(filename) + break; + end + if (isRoboticsToolboxAvailable) + waitfor(r); + else + pause(1/desiredRate); + end + end + result = contents; + + function name = getRepoName() + commandString = 'git rev-parse --show-toplevel'; + [status, result] = system(commandString); + if status + ME = MException('Git:couldntExecuteGitCommand', ... + 'git command %s resulted in failure!', commandString); + throw(ME); + end + result = result(1:end-1); % remove newline. + [~,name,~] = fileparts(result); diff --git a/source/installDeps.m b/source/installDeps.m index 23a3ce1..e1bc617 100644 --- a/source/installDeps.m +++ b/source/installDeps.m @@ -12,30 +12,48 @@ % used to manually install deps by calling: % pm.install(); % It can also be used for adding dep paths to path by calling -% addpath(pm.genPath()) +% addpath(pm.genPath{:}) % % Usage example: % % Modify getDepList.m to return the list of all dependencies. % % Then simply call this any time you want to install/update: % installDeps -function varargout = installDeps( depList, depSubDir, varargin ) - +function varargout = installDeps(varargin) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Directory of dependencies -if nargin < 2 || isempty(depSubDir) - depSubDir = fullfile('.', 'external'); - depSubDir = getDepDirPath( depSubDir ); +% Get the list of dependencies +folderName = pwd; +nonGitPaths = genNonGitPath(folderName); + +if (all(cellfun(@exist, nonGitPaths)== 7)) + addpath(nonGitPaths{:}); + s = which('installDeps.m', '-ALL'); + if length(s) >= 1 + installDepsPath = s{1}; + dpDirPth = fileparts(installDepsPath); + getDepListFunction = fullfile(dpDirPth, 'getDepList.m'); + run(getDepListFunction); + depList = ans; + + depSubDir = fullfile(fileparts(installDepsPath),'external'); + + if nargin ~= 0 + depList = varargin{1}; + end + + installPackMan( depSubDir, depList ); + end +else + error('Unexistent path found!'); end -installPackMan( depSubDir ); -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Get the list of dependencies -if nargin < 1 || isempty(depList) - depList = getDepList(); +if nargin ~= 0 + depList = varargin{1}; +else + end -pm = PackMan(depList, depSubDir, varargin{:}); % Install other dependencies +pm = PackMan(depList, depSubDir); % Install other dependencies if nargout < 1 pm.install(); @@ -43,8 +61,6 @@ varargout{1} = pm; end -end - function depDirPath = getDepDirPath( depSubDir ) % Generates path to dependency directory based on the path of the current % file @@ -57,9 +73,7 @@ [thisFileDir, ~, ~] = fileparts(thisFilePath); depDirPath = fullfile(thisFileDir, depSubDir); -end - -function installPackMan( depDirPath ) +function installPackMan( depDirPath, depList ) % Makes sure DepMat is available and in the path, so that PackMan can % install other dependencies % Inputs: @@ -69,18 +83,30 @@ function installPackMan( depDirPath ) % Usage example: % installPackMan( depDirPath ); -packManDir = fullfile(depDirPath, 'PackMan'); +packageManagerName = 'PackMan'; +packManDir = fullfile(depDirPath, packageManagerName); +packageManagerDep = depList(strcmp({depList.Name}, packageManagerName)); try - repoUrl = 'https://github.com/OmidS/PackMan.git'; - command = ['git clone ', repoUrl, ' "',packManDir,'"']; +% Name, Branch, Url, FolderName, Commit, GetLatest + command = ['git clone --single-branch --branch ', packageManagerDep.Branch,' ', packageManagerDep.Url, ' "',packManDir,'"']; [status, cmdout] = system(command); if (~status), fprintf('%s', cmdout); end -catch ME +catch end packManSourceDir = fullfile(packManDir,'source'); +packManPath = genNonGitPath(packManSourceDir); +addpath(packManPath{:}); -addpath(genpath(packManSourceDir)); - -end \ No newline at end of file +function pathList = genNonGitPath(folderName) +%genPath - Description +% +% Syntax: output = genPath(input) +% +% Long description + +paths = genpath(folderName); +pathList = split(paths, ';'); +pathList = rmmissing(pathList); +pathList = pathList(~contains(pathList, '\.git')); \ No newline at end of file diff --git a/source/tests/prepareTestEnvironment.m b/source/tests/prepareTestEnvironment.m new file mode 100644 index 0000000..bffe641 --- /dev/null +++ b/source/tests/prepareTestEnvironment.m @@ -0,0 +1,35 @@ +function toRemoveLater = prepareTestEnvironment() +%PREPARETESTENVIRONMENT Summary of this function goes here +% Detailed explanation goes here +currentWorkingDir = pwd; +externalFolderPath = fullfile(currentWorkingDir,'source','external'); +currentPath = path; +currentPathList = split(currentPath, ';'); +currentPathList = rmmissing(currentPathList); +sourceFolderPath =fullfile(currentWorkingDir,'source'); +toAddBefore = currentPathList(strcmp(currentPathList, sourceFolderPath)); +if (isempty(toAddBefore)) + addpath(sourceFolderPath); + currentPathList = [currentPathList; {sourceFolderPath}]; +end +if exist(externalFolderPath, 'dir') + nonGitExternalFolderPaths = genNonGitPath(externalFolderPath); + externalFolderPathsToRemove = nonGitExternalFolderPaths(isTheres(currentPathList, nonGitExternalFolderPaths)); + if (~isempty(externalFolderPathsToRemove)) + rmpath(externalFolderPathsToRemove{:}); + end + rmdir(externalFolderPath, 's'); +end +packageFile = fullfile(currentWorkingDir,'package.json'); +if exist(packageFile, 'file') + delete(packageFile); +end +nonGitPath = genNonGitPath(currentWorkingDir); +toRemoveLater = nonGitPath(isTheres(currentPathList, nonGitPath)); +toRemoveLater = toRemoveLater(~strcmp(toRemoveLater, fullfile(currentWorkingDir,'source','tests'))); + +function result = isThere(setOfElements, element) +result = ~isempty(setOfElements(strcmp(setOfElements, element))); + +function result = isTheres(superSet, subSet) +result = cellfun(@(x)isThere(superSet, x), subSet); \ No newline at end of file diff --git a/source/tests/prepareTestEnvironmentAndInstall.m b/source/tests/prepareTestEnvironmentAndInstall.m new file mode 100644 index 0000000..464b2a0 --- /dev/null +++ b/source/tests/prepareTestEnvironmentAndInstall.m @@ -0,0 +1,8 @@ +function pm = prepareTestEnvironmentAndInstall(depList) +%PREPARETESTENVIRONMENTANDINSTALL Summary of this function goes here +% Detailed explanation goes here +toRemoveLater = prepareTestEnvironment(); +pm = installDeps(depList); +pm.install(); +rmpath(toRemoveLater{:}); + diff --git a/source/tests/testPackMan.m b/source/tests/testPackMan.m index 87167db..b96f483 100644 --- a/source/tests/testPackMan.m +++ b/source/tests/testPackMan.m @@ -5,32 +5,46 @@ %% Main function to generate tests function tests = testPackMan tests = functiontests(localfunctions); +disp tests end %% Test Functions function testThatPackManConstructorWorks(testCase) % Test specific code - pm = PackMan(); - pm.install(); + depList = {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; + depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); + + pm = prepareTestEnvironmentAndInstall(depList); verifyEqual(testCase,class(pm),'PackMan'); end function testThatPackManRelativePathsWork(testCase) % Test specific code - wDir = pwd; - pm = PackMan(); - pm.install(); - - expectedDepDirPath = fullfile(wDir, './external'); + depList = {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; + depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); + + pm = prepareTestEnvironmentAndInstall(depList); + currentWorkingDir = pwd; + expectedDepDirPath = fullfile(currentWorkingDir, 'source', 'external'); verifyEqual(testCase,pm.depDirPath, expectedDepDirPath); - expectedPackagePath = fullfile(wDir, './package.mat'); + expectedPackagePath = fullfile(currentWorkingDir, './package.json'); verifyEqual(testCase,pm.packageFilePath, expectedPackagePath); end - + function testThatPackManGeneratesPackageFile(testCase) % Test specific code - pm = PackMan(); + depList = [ + {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; + {'DepMat', 'master', 'https://github.com/OmidS/depmat.git', 'depmat', '', true}; + ]; + depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); + + prepareTestEnvironment(); + pm = installDeps(depList); + + verifyTrue(testCase, ~exist(pm.packageFilePath, 'file')) + pm.install(); verifyTrue(testCase, exist(pm.packageFilePath, 'file')~=false ); @@ -38,136 +52,140 @@ function testThatPackManGeneratesPackageFile(testCase) function testThatPackManFetchesRepos(testCase) % Test specific code - depList = DepMatRepo('DepMat', 'master', 'https://github.com/OmidS/depmat.git', 'depmat', '', true); - pm = PackMan( depList ); - pm.install(); + depList = [ + {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; + {'DepMat', 'master', 'https://github.com/OmidS/depmat.git', 'depmat', '', true}; + ]; + depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); + + pm = prepareTestEnvironmentAndInstall(depList); - depDir = fullfile(pm.depDirPath, depList.FolderName); - verifyTrue(testCase, exist(depDir, 'dir')~=false ); + for i=1:length(depList) + depDir = fullfile(pm.depDirPath, depList(i).FolderName); + verifyTrue(testCase, exist(depDir, 'dir')~=false ); + end depListOnFile = PackMan.loadFromPackageFile( pm.packageFilePath ); verifyEqual(testCase,length(depList), length(depListOnFile)); for i = 1:length(depList) - rId = find( strcmp( {depListOnFile.Name}, depList(i).Name) ); + rId = strcmp( {depListOnFile.Name}, depList(i).Name) ; verifyEqual(testCase, depList(i).Url, depListOnFile(rId).Url); end end function testThatPackManCanFetchesSpecificCommits(testCase) % Test specific code - depList = DepMatRepo('DepMat1', 'master', 'https://github.com/OmidS/depmat.git', 'depmat1', 'f3810b050186a2e1e5e3fbdb64dd7cd8f3bc8528', false); - depList(end+1, 1) = DepMatRepo('DepMat2', 'master', 'https://github.com/OmidS/depmat.git', 'depmat2', '95fe15dc04406846857e1601f5954a1b4997313b', false); + depList = [ + {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; + {'DepMat1', 'master', 'https://github.com/OmidS/depmat.git', 'depmat1', 'f3810b050186a2e1e5e3fbdb64dd7cd8f3bc8528', false}; + {'DepMat2', 'master', 'https://github.com/OmidS/depmat.git', 'depmat2', '95fe15dc04406846857e1601f5954a1b4997313b', false}; + ]; + depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); - pm = PackMan( depList ); - pm.install(); + pm = prepareTestEnvironmentAndInstall(depList); - depDir1 = fullfile(pm.depDirPath, depList(1).FolderName); depDir2 = fullfile(pm.depDirPath, depList(2).FolderName); + depDir3 = fullfile(pm.depDirPath, depList(3).FolderName); addedFile = 'TestRepoList.m'; % This is a file we expect to exist in commit 2 but not in commit 1 - verifyTrue(testCase, exist( fullfile(depDir1, addedFile) , 'file')==false ); - verifyTrue(testCase, exist( fullfile(depDir2, addedFile) , 'file')~=false ); + verifyTrue(testCase, exist( fullfile(depDir2, addedFile) , 'file')==false ); + verifyTrue(testCase, exist( fullfile(depDir3, addedFile) , 'file')~=false ); % Check commit ids in package file depListOnFile = PackMan.loadFromPackageFile( pm.packageFilePath ); - for i = 1:length(depList) - rId = find( strcmp( {depListOnFile.Name}, depList(i).Name) ); + for i = 2:length(depList) + rId = strcmp( {depListOnFile.Name}, depList(i).Name) ; verifyEqual(testCase, depListOnFile(rId).Commit, depList(i).Commit ); end end function testThatPackManAutoInstallsOnlyWhenItHasNoOutput(testCase) % Test specific code - depList = DepMatRepo('DepMat1', 'master', 'https://github.com/OmidS/depmat.git', 'depmat1', '', false); + depList = [ + {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; + {'DepMat1', 'master', 'https://github.com/OmidS/depmat.git', 'depmat1', '', false}; + ]; + + depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); - packageDir = fullfile('./external', depList(1).FolderName); + prepareTestEnvironment(); + externalFolder = fullfile(pwd, 'source', 'external'); + packageDir = fullfile(externalFolder, depList(2).FolderName); verifyTrue(testCase, exist( packageDir , 'dir')==false ); - pm = PackMan( depList ); + pm = installDeps(depList); verifyTrue(testCase, exist( packageDir , 'dir')==false ); pm.install(); verifyTrue(testCase, exist( packageDir , 'dir')~=false ); - depList(end+1, 1) = DepMatRepo('DepMat2', 'master', 'https://github.com/OmidS/depmat.git', 'depmat2', '', false); - packageDir = fullfile('./external', depList(2).FolderName); + depList = [ + {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; + {'DepMat1', 'master', 'https://github.com/OmidS/depmat.git', 'depmat1', '', false}; + {'DepMat2', 'master', 'https://github.com/OmidS/depmat.git', 'depmat2', '', false}; + ]; + depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); + + prepareTestEnvironment(); + packageDir = fullfile(externalFolder, depList(3).FolderName); verifyTrue(testCase, exist( packageDir , 'dir')==false ); - PackMan( depList ); + installDeps(depList); verifyTrue(testCase, exist( packageDir , 'dir')~=false ); end function testThatPackManRejectsInvalidDepLists(testCase) % Test specific code - depList = DepMatRepo('DepMat', 'master', 'https://github.com/OmidS/depmat.git', 'depmat1', 'f3810b050186a2e1e5e3fbdb64dd7cd8f3bc8528', false); - depList(end+1, 1) = DepMatRepo('DepMat', 'master', 'https://github.com/OmidS/depmat.git', 'depmat2', '95fe15dc04406846857e1601f5954a1b4997313b', false); - verifyError(testCase, @()( PackMan(depList) ), 'PackMan:DepListError' ); + depList = [ + {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; + {'DepMat', 'master', 'https://github.com/OmidS/depmat.git', 'depmat1', 'f3810b050186a2e1e5e3fbdb64dd7cd8f3bc8528', false}; + {'DepMat', 'master', 'https://github.com/OmidS/depmat.git', 'depmat2', '95fe15dc04406846857e1601f5954a1b4997313b', false}; + ]; + depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); + prepareTestEnvironment(); + verifyError(testCase, @()( installDeps(depList) ), 'PackMan:DepListError' ); end function testThatPackManReturnsDepPaths(testCase) % Test specific code - depList = DepMatRepo('DepMat', 'master', 'https://github.com/OmidS/depmat.git', 'depmat', '', true); - pm = PackMan( depList ); - pm.install(); + depList = [ + {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; + {'DepMat', 'master', 'https://github.com/OmidS/depmat.git', 'depmat', '', true}; + ]; + depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); + pm = prepareTestEnvironmentAndInstall(depList); paths = pm.genPath(); - expectedPaths = [fullfile(pm.parentDir, './external/depmat/tests'),';', ... - fullfile(pm.parentDir, './external/depmat'),';', ... - pm.parentDir,';']; + expectedPaths = [ + {pm.parentDir } + {fullfile(pm.parentDir, 'source') } + {fullfile(pm.parentDir, 'source', 'external') } + {fullfile(pm.parentDir, 'source', 'external', 'PackMan') } + {fullfile(pm.parentDir, 'source', 'external', 'PackMan', 'source') } + {fullfile(pm.parentDir, 'source', 'external', 'depmat') } + {fullfile(pm.parentDir, 'source', 'external', 'depmat', 'tests') } + {fullfile(pm.parentDir, 'source', 'tests') } + ]; verifyEqual(testCase, paths, expectedPaths); end function testThatPackManRecursiveWorks(testCase) % Test specific code - depList = DepMatRepo('matlabPackManRecursiveSample', 'master', 'https://github.com/OmidS/matlabPackManRecursiveSample.git', 'matlabPackManRecursiveSample', '', true); - pm = PackMan( depList ); - pm.install(); + depList = [ + {'PackMan', 'release', 'https://github.com/DanielAtKrypton/PackMan.git', 'PackMan', '', true}; + {'PackManRecursiveSample', 'master', 'https://github.com/DanielAtKrypton/PackManRecursiveSample.git', 'PackManRecursiveSample', '', true}; + ]; + + depList = cell2struct(depList, {'Name', 'Branch', 'Url', 'FolderName', 'Commit', 'GetLatest'}, 2); + pm = prepareTestEnvironmentAndInstall(depList); paths = pm.genPath(); - expectedPaths = [fullfile(pm.parentDir, './external/matlabPackManRecursiveSample/external/depmat/tests'),';', ... - fullfile(pm.parentDir, './external/matlabPackManRecursiveSample/external/depmat'),';', ... - fullfile(pm.parentDir, './external/matlabPackManRecursiveSample/external/matlabPackManSample/external/depmat/tests'),';', ... - fullfile(pm.parentDir, './external/matlabPackManRecursiveSample/external/matlabPackManSample/external/depmat'),';', ... - fullfile(pm.parentDir, './external/matlabPackManRecursiveSample/external/matlabPackManSample'),';', ... - fullfile(pm.parentDir, './external/matlabPackManRecursiveSample'),';', ... - pm.parentDir,';']; + expectedPaths = [ + {pm.parentDir } + {fullfile(pm.parentDir, 'source') } + {fullfile(pm.parentDir, 'source', 'external') } + {fullfile(pm.parentDir, 'source', 'external', 'PackMan') } + {fullfile(pm.parentDir, 'source', 'external', 'PackManRecursiveSample') } + {fullfile(pm.parentDir, 'source', 'external', 'PackMan', 'source') } + {fullfile(pm.parentDir, 'source', 'tests') } + ]; verifyEqual(testCase, paths, expectedPaths); end - -%% Helper functions -function [depDir, packageFile] = getPaths() - -p = fileparts( mfilename('fullpath') ); -depDir = fullfile(p, 'external'); -packageFile = fullfile(p, 'package.mat'); - -end - -%% Optional file fixtures -function setupOnce(testCase) % do not change function name -% set a new path, for example -addpath('../'); - -end - -function teardownOnce(testCase) % do not change function name -% change back to original path, for example - -end - -%% Optional fresh fixtures -function setup(testCase) % do not change function name -% open a figure, for example - -[depDir, packageFile] = getPaths(); -if exist(depDir, 'dir'), delete(depDir); end -if exist(packageFile, 'file'), delete(packageFile); end - -end - -function teardown(testCase) % do not change function name -% close figure, for example - -[depDir, packageFile] = getPaths(); -if exist(depDir, 'dir'), rmdir(depDir, 's'); end -if exist(packageFile, 'file'), delete(packageFile); end - -end \ No newline at end of file