diff --git a/.travis.yml b/.artenolis.yml similarity index 83% rename from .travis.yml rename to .artenolis.yml index 74f4b2a..8f51993 100644 --- a/.travis.yml +++ b/.artenolis.yml @@ -48,7 +48,7 @@ script: - cd $CURRENT_DIR; # launch the tests - - sh ./runtests.sh; + - sh ./.artenolis/runtests.sh; - cd ~/fork-MATLAB.devTools.CI; - git reset --hard origin/develop; @@ -58,4 +58,8 @@ after_success: # remove the cloned fork-repo - if [ "$MATLAB_VER" == "R2016b" ]; then bash <(curl -s https://codecov.io/bash) -f "!*.lst"; + export PATH="/home/sbg-jenkins/.local/bin":$PATH; + cd $CURRENT_DIR; + pip install --upgrade --user -r docs/requirements.txt; + python -c "from documenter.deploy import Documentation; doc = Documentation('github.com/opencobra/MATLAB.devTools', ci='jenkins'); doc.deploy()"; fi diff --git a/.artenolis/runtests.sh b/.artenolis/runtests.sh new file mode 100644 index 0000000..a401247 --- /dev/null +++ b/.artenolis/runtests.sh @@ -0,0 +1,5 @@ +#!/bin/sh +cd ./test +/mnt/prince-data/MATLAB/$MATLAB_VER/bin/./matlab -nodesktop -nosplash -r "launchTests;" < inputCI.txt; +CODE=$? +exit $CODE diff --git a/.gitignore b/.gitignore index fafff2e..1ee3278 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,40 @@ +build +*.*~ .DS_Store -Thumbs.db +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows shortcuts +*.lnk + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Documentation related files +docs/source/_static/json/functions.json +*.pyc diff --git a/FAQ.md b/FAQ.md deleted file mode 100644 index 7b8735e..0000000 --- a/FAQ.md +++ /dev/null @@ -1,52 +0,0 @@ -# Frequently Asked Questions (FAQ) - -## Mismatch of the version of `openSSL` (Linux) - -You might be in the situation that you receive the following error: -```` -OpenSSL version mismatch. Built against 1000207f, you have 100010bf -```` -In that case, you should run the following command: -```` -sudo mv /bin/glnxa64/libcrypto.so.1.0.0 /bin/glnxa64/libcrypto.so.1.0.0_bk -```` -where `` corresponds to the installation of `MATLAB`, e.g., `/usr/local/MATLAB/R2016b` - -## How do I submit a Pull Request? - -Once you submit your contribution (menu item 3), you will be presented with a link that leads you directly to the pull request (PR). - -## Turn on the verbose mode - -If you encounter a problem, or suspect that something is not behaving properly, please run: -``` ->> contribute(true) -``` -and follow the process as normally. You can also set `gitConf.verbose = true;` in `assets/confDevTools.m`. - -## Resolve unexpected behavior - reset - -If you encounter unexpected behavior, please try to reset the `devTools` with: -``` ->> resetDevTools -``` - -If you have files or changes that appear and would like to reset your local fork (without re-cloning) again, type: -``` ->> resetLocalFork -``` - -## How can I abort a process? - -You can abort any process using `CTRL-C` (hit `CTRL` and `C` on your keyboard). - -## How should I name my contribution? - -Initiate a contribution per theme/topic/feature/bug fix that you work on. Don't mix features and think of an explicit name, i.e. `bug-fix-function1` or `add-tests-function2`. Avoid generic names, such as `my-great-feature` or `fix` or `contribution-myName`. - -## How can I check the history of a file? - -You can check the history of a file by typing in MATLAB: -``` ->> history('fileName.m') -``` diff --git a/PREREQUISITES.md b/PREREQUISITES.md deleted file mode 100644 index f923a81..0000000 --- a/PREREQUISITES.md +++ /dev/null @@ -1,78 +0,0 @@ -# Pre-requisites - -## GitHub SSH configuration - -You have to register the SSH key of each computer that you are planning to use the `MATLAB.devTools` on. - -- **Check if you already have an SSH key:** -```` -$ ls -al ~/.ssh -```` -If there is a file with an extension `.pub`, you already have an SSH key. Now, you have to **add your SSH key to Github**. More help is [here](https://help.github.com/articles/checking-for-existing-ssh-keys/). - -- **Generate the SSH key on your computer:** -If you don't have yet an SSH key (see previous step), you have to generate one (more help is [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/)): -```` -$ ssh-keygen -t rsa -C "first.last@server.com" -```` - -- **Add the SSH** to [your Github account](https://github.com/settings/keys) by following the steps [here](https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/). - -## Can I check if everything is properly set up before I start? - -Please ensure that you have a working `MATLAB` installation. - -You can check if you have a working installation of `git` by typing in the terminal (or GUI Bash): -```bash -$ git --version -``` -This will return `git version 2.10.1 [...]` or similar with another version number. - -You can then check if your `git` is properly configured by typing in the terminal (or GUI Bash): -```bash -$ git config --get user.github-username -``` -which will return your Github username if everything is properly set up. Similarly, check the configured email by typing in the terminal (or GUI Bash): -```bash -$ git config --get user.email -``` - -You can check if you have a working installation of `curl` by typing in the terminal (or GUI Bash): -```bash -$ curl --version -``` -which will return `curl 7.51.0 [...]` or similar with another version number. - -## System configuration - -You must have `git` and `curl` installed. Please also ensure that you have `MATLAB` [installed](https://nl.mathworks.com/help/install/). - -**Linux (Ubuntu or Debian)** - -```bash -$ sudo apt-get install git-all curl -``` - -**macOS** - -In order to install `git`, install the [Xcode Command Line Tools](http://osxdaily.com/2014/02/12/install-command-line-tools-mac-os-x/). For `curl`, follow the instructions [here](http://macappstore.org/curl/). - -**Windows** - -Please download the `git` tools for Windows from [here](https://git-scm.com/download/win). During the installation process, please ensure that you select **Use Git Bash and optional Unix tools from the Windows Command prompt**. In addition, please make sure that you select **Checkout as-is, commit Unix-style line endings**. - -
-   . -
- -## Github and local `git` configuration - -If you don't have a GitHub account, please sign up [here](https://github.com/join). For the very first time, you must **fork** the repository of The COBRA Toolbox. Browse to the [original repository](https://github.com/opencobra/cobratoolbox) and click on the button -. - -On **Linux (Ubuntu)** or **macOS**, start the terminal (or any other shell). On **Windows**, start `GUI Bash`. Then type -```bash -$ git config --global user.github-username "yourGitHubUsername" -$ git config --global user.email "first.last@server.com" -``` -Please replace `"yourGitHubUsername"` and `"first.last@server.com"` with your respective credentials. diff --git a/README.md b/README.md deleted file mode 100644 index af1872f..0000000 --- a/README.md +++ /dev/null @@ -1,80 +0,0 @@ -

- -

-
- -| MATLAB R2016b | MATLAB R2015b | Code Coverage | Code Grade | -|--------|--------|--------|--------| -| [![Build Status](https://prince.lcsb.uni.lu/jenkins/buildStatus/icon?job=devTools-branches-auto/MATLAB_VER=R2016b)](https://prince.lcsb.uni.lu/jenkins/job/devTools-branches-auto/MATLAB_VER=R2016b/) | [![Build Status](https://prince.lcsb.uni.lu/jenkins/buildStatus/icon?job=devTools-branches-auto/MATLAB_VER=R2015b)](https://prince.lcsb.uni.lu/jenkins/job/devTools-branches-auto/MATLAB_VER=R2015b/)| [![codecov](https://codecov.io/gh/opencobra/MATLAB.devTools/branch/master/graph/badge.svg)](https://codecov.io/gh/opencobra/MATLAB.devTools/branch/master) | ![Code grade](https://prince.lcsb.uni.lu/jenkins/userContent/codegrade-MATLABdevTools.svg?maxAge=0 "Ratio of the number of inefficient code lines and the total number of lines of code (in percent). A: 0-3%, B: 3-6%, C: 6-9%, D: 9-12%, E: 12-15%, F: > 15%.") - -# MATLAB.devTools - Contribute the smart way - -## Pre-requisites - -Please follow the [configuration instructions](https://github.com/opencobra/MATLAB.devTools/blob/master/PREREQUISITES.md) carefully. You may skip this if your system is already set up and you have `git` configured. - -warning **IMPORTANT**: Please make sure that you have configured your SSH key in Github as explained [here](https://github.com/opencobra/MATLAB.devTools/blob/master/PREREQUISITES.md). - -## Installation - -Download this repository (the folder `./MATLAB.devTools/` will be created). You can clone the repository using: -````bash -$ git clone git@github.com:opencobra/MATLAB.devTools.git MATLAB.devTools -```` -warning Run this command in `Terminal` (on macOS and Linux) or in `Git Bash` (on Windows) - **not** in Matlab. - - -## Do you want to contribute to The COBRA Toolbox? - -Please follow the [installation and contributing instructions](https://github.com/opencobra/cobratoolbox/blob/master/README.md). - -[![asciicast](https://asciinema.org/a/7zg2ce5gfth7ruywptgc3i3yy.png)](https://asciinema.org/a/7zg2ce5gfth7ruywptgc3i3yy) - -## How do I use the `MATLAB.devTools`? - -Making a contribution to any `git` repository from Matlab is straightforward. Type in Matlab within the `MATLAB.devTools` folder: -```Matlab ->> contribute -``` - -You will then be presented by a menu: -``` - [1] Start a new feature (branch). - [2] Select an existing feature (branch) to work on. - [3] Publish a feature (branch). - [4] Delete a feature (branch). - [5] Update the fork. - --> Please select what you want to do (enter the number): -``` - -The original repository will be downloaded (cloned) the first time to a folder named `fork-gitRepoName`. **Only files in the `fork-gitRepoName` folder** will be considered for contribution (any changes made to a downloaded official `git` repository will be ignored). - -warning If you get stuck or are faced with an system error message, please read the [FAQ](https://github.com/opencobra/MATLAB.devTools/blob/master/FAQ.md). - -## How can I update my fork without contributing? - -In order to only update your fork, run `>> contribute` and select menu item `[5]`. - -## Configure the `MATLAB.devTools` for another repository - -warning The `MATLAB.devTools` can only be used with **publicly accessible** repositories. - -If you want to use the `MATLAB.devTools` with a repository other than the default repository, you must set the following variables: - -```Matlab -launcher = '\n\n ~~~ MATLAB.devTools ~~~\n\n'; % a message for the repository (any string) -remoteRepoURL = 'https://server.com/repositoryName.git'; % the remote url -nickName = 'repoNickName'; % a nickName of the repository (any string) -verbose = false; % turn the verbose mode on (true) or off (false) -``` -and run: -```Matlab ->> confDevTools(launcher, remoteRepoURL, nickName, verbose); % sets the configuration -``` - -In order to reset the configuration, type: -```Matlab ->> resetDevTools(); -``` -If you want your changes to be permanent, you can set the above mentioned variables in `./assets/confDevTools.m`. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..5a1e307 --- /dev/null +++ b/README.rst @@ -0,0 +1,262 @@ +.. raw:: html + +

+ +

+ +

+ MATLAB.devTools - Contribute the smart way +

+ ++----------------+----------------+---------------+--------------+ +| MATLAB R2016b | MATLAB R2015b | Code Coverage | Code Grade | ++================+================+===============+==============+ +| |Build Status| | |Build Status| | |codecov| | |Code grade| | ++----------------+----------------+---------------+--------------+ + +.. begin-description-marker + +All repositories on Github are version controlled using `git +`__, a free and open-source distributed, version control +system, which tracks changes in computer files and is used for coordinating +work on those files by multiple people. + +In order to lower the technological barrier to the use of the popular software +development tool `git `__, we have developed +`MATLAB.devTools`, a new user-friendly software extension that enables +submission of new COBRA software and tutorials, in particular for `The COBRA +Toolbox `__ and the +`COBRA.tutorials `__. + +The `MATLAB.devTools `__ are +highly recommended for contributing code (in particular `MATLAB` code) to +existing repositories in a user-friendly and convenient way, even for those +without basic knowledge of `git`. + +.. end-description-marker + + +Pre-requisites +-------------- + +.. begin-prerequisites-marker + +Please follow the `configuration +instructions `__ +carefully. You may skip this if your system is already set up and you +have ``git`` configured. + +|important| **IMPORTANT**: Please make sure that you have configured your SSH key +in Github as explained +`here `__. + +.. end-prerequisites-marker + +Installation +------------ + +.. begin-installation-marker + +Download this repository (the folder ``./MATLAB.devTools/`` will be +created). You can clone the repository using: + +.. code:: bash + + $ git clone git@github.com:opencobra/MATLAB.devTools.git MATLAB.devTools + +|important| Run this command in ``Terminal`` (on |macOS| and |linux|) or in ``Git Bash`` (on |windows|) - +**not** in |matlab|. + +Some issues that can arise during installation are addressed in the +`FAQ `__. + +.. end-installation-marker + +Do you want to contribute to The COBRA Toolbox? +----------------------------------------------- + +|asciicast| + +More information about `the COBRA Toolbox +`__ is given `here +`__. + +How do I use the ``MATLAB.devTools``? +------------------------------------- + +.. begin-getstarted-marker + +Making a contribution to any ``git`` repository from |matlab| is straightforward. +Type in |matlab| within the ``MATLAB.devTools`` folder: + +.. code:: matlab + + >> contribute + +You will then be presented by a menu: + +:: + + [1] Start a new feature (branch). + [2] Select an existing feature (branch) to work on. + [3] Publish a feature (branch). + [4] Delete a feature (branch). + [5] Update the fork. + + -> Please select what you want to do (enter the number): + +The original repository will be downloaded (cloned) the first time to a +folder named ``fork-gitRepoName``. **Only files in the +fork-gitRepoName folder** will be considered for contribution (any +changes made to a downloaded official ``git`` repository will be +ignored). + +|important| If you get stuck or are faced with an system error message, please read +the `FAQ `__. + +.. end-getstarted-marker + +How can I update my fork without contributing? +---------------------------------------------- + +In order to only update your fork, run ``>> contribute`` and select menu +item ``[5]``. + +Configure the ``MATLAB.devTools`` for ``COBRA.tutorials`` +--------------------------------------------------------- + +.. begin-contribute-cobratutorials-marker + +If you want to use the ``MATLAB.devTools`` when contributing to the +`COBRA.tutorials `__, you can simply configure +the ``MATLAB.devTools`` on-the-fly by typing: + +.. code:: matlab + + >> contribute('opencobra/COBRA.tutorials') + +.. end-contribute-cobratutorials-marker + + +Configure the ``MATLAB.devTools`` for another repository +-------------------------------------------------------- + +.. begin-contribute-other-repo-marker + +|important| The ``MATLAB.devTools`` can only be used with **publicly accessible** repositories. + +If you want to use the ``MATLAB.devTools`` with a repository other than +the default repository, you may run: + +.. code:: matlab + + >> contribute('userName/repositoryName') + +where ``userName`` is the name on Github of the organization or the user, and +``repositoryName`` is the name of the repository. The URL of the repository +would be `https://github.com/userName/repositoryName`. Please note that this +command looks for a repository on `github.com `__. + +.. end-contribute-other-repo-marker + +How to reset the ``MATLAB.devTools`` +------------------------------------ + +.. begin-reset-marker + +In order to reset the configuration of the ``MATLAB.devTools``, type: + +.. code:: matlab + + >> resetDevTools(); + +This performs a so-called `soft` reset (clears the local configuration). In +order to perform a hard reset (clears and resets the local ``git`` +configuration), run: + +.. code:: matlab + + >> resetDevTools(true); + +Once the devTools have been `hard` reset, all details for the configuration +have to be set again next time ``contribute`` is run. + +.. end-reset-marker + +How to cite the ``MATLAB.devTools`` +----------------------------------- + +.. begin-how-to-cite-marker + +As the ``MATLAB.devTools`` have first been developed for the COBRA Toolbox, the +paper of The COBRA Toolbox shall we cited when referring to the ``MATLAB.devTools``. + + Laurent Heirendt & Sylvain Arreckx, Thomas Pfau, Sebastian N. + Mendoza, Anne Richelle, Almut Heinken, Hulda S. Haraldsdottir, Jacek + Wachowiak, Sarah M. Keating, Vanja Vlasov, Stefania Magnusdottir, + Chiam Yu Ng, German Preciat, Alise Zagare, Siu H.J. Chan, Maike K. + Aurich, Catherine M. Clancy, Jennifer Modamio, John T. Sauls, + Alberto Noronha, Aarash Bordbar, Benjamin Cousins, Diana C. El + Assal, Luis V. Valcarcel, Inigo Apaolaza, Susan Ghaderi, Masoud + Ahookhosh, Marouen Ben Guebila, Andrejs Kostromins, Nicolas + Sompairac, Hoai M. Le, Ding Ma, Yuekai Sun, Lin Wang, James T. + Yurkovich, Miguel A.P. Oliveira, Phan T. Vuong, Lemmer P. El Assal, + Inna Kuperstein, Andrei Zinovyev, H. Scott Hinton, William A. + Bryant, Francisco J. Aragon Artacho, Francisco J. Planes, Egils + Stalidzans, Alejandro Maass, Santosh Vempala, Michael Hucka, Michael + A. Saunders, Costas D. Maranas, Nathan E. Lewis, Thomas Sauter, + Bernhard Ø. Palsson, Ines Thiele, Ronan M.T. Fleming, **Creation and + analysis of biochemical constraint-based models: the COBRA Toolbox + v3.0** (submitted), 2017, + `arXiv:1710.04038 `__. + +.. end-how-to-cite-marker + + +.. |Build Status| image:: https://prince.lcsb.uni.lu/jenkins/buildStatus/icon?job=devTools-branches-auto/MATLAB_VER=R2016b + :target: https://prince.lcsb.uni.lu/jenkins/job/devTools-branches-auto/MATLAB_VER=R2016b/ +.. |Build Status| image:: https://prince.lcsb.uni.lu/jenkins/buildStatus/icon?job=devTools-branches-auto/MATLAB_VER=R2015b + :target: https://prince.lcsb.uni.lu/jenkins/job/devTools-branches-auto/MATLAB_VER=R2015b/ +.. |codecov| image:: https://codecov.io/gh/opencobra/MATLAB.devTools/branch/master/graph/badge.svg + :target: https://codecov.io/gh/opencobra/MATLAB.devTools/branch/master +.. |Code grade| image:: https://prince.lcsb.uni.lu/jenkins/userContent/codegrade-MATLABdevTools.svg?maxAge=0 + + +.. begin-screencast-marker + +.. |asciicast| image:: https://asciinema.org/a/7zg2ce5gfth7ruywptgc3i3yy.png + :target: https://asciinema.org/a/7zg2ce5gfth7ruywptgc3i3yy + +.. end-screencast-marker + + +.. begin-icon-marker +.. |macos| raw:: html + + macOS + +.. |linux| raw:: html + + linux + +.. |windows| raw:: html + + windows + +.. |matlab| raw:: html + + matlab + +.. |important| raw:: html + + bulb + +.. |warning| raw:: html + + warning + +.. |bulb| raw:: html + + bulb + +.. end-icon-marker diff --git a/assets/confDevTools.m b/assets/confDevTools.m deleted file mode 100644 index 9310add..0000000 --- a/assets/confDevTools.m +++ /dev/null @@ -1,37 +0,0 @@ -function confDevTools(launcher, remoteRepoURL, nickName, verbose) -% devTools -% -% PURPOSE: define the configuration of the devTools -% - - global gitConf - global gitCmd - - % definition of parameters - gitConf.leadForkDirName = 'fork-'; - gitConf.exampleBranch = 'add-constraints'; - - if nargin < 4 % default values - gitConf.verbose = false; - gitConf.launcher = '\n\n _____ _____ _____ _____ _____ |\n / ___| / _ \\ | _ \\ | _ \\ / ___ \\ | COnstraint-Based Reconstruction and Analysis\n | | | | | | | |_| | | |_| | | |___| | | The COBRA Toolbox - 2017\n | | | | | | | _ { | _ / | ___ | |\n | |___ | |_| | | |_| | | | \\ \\ | | | | | Documentation:\n \\_____| \\_____/ |_____/ |_| \\_\\ |_| |_| | http://opencobra.github.io/cobratoolbox\n | \n\n'; - gitConf.remoteRepoURL = 'https://github.com/opencobra/cobratoolbox.git'; - gitConf.nickName = 'cobratoolbox'; - else - gitConf.verbose = verbose; - gitConf.launcher = launcher; - gitConf.remoteRepoURL = remoteRepoURL; - gitConf.nickName = nickName; - end - - % define the URL of the devTools - gitConf.devToolsURL_SSH = 'git@github.com:opencobra/MATLAB.devTools.git'; - gitConf.devToolsURL_HTTPS = 'https://github.com/opencobra/MATLAB.devTools.git'; - gitConf.devTools_name = 'MATLAB.devTools'; - - % definition of commands - gitCmd.lead = 'dev> '; - gitCmd.success = ' (Success) '; - gitCmd.fail = ' (Error) '; - gitCmd.trail = '\n'; - -end diff --git a/contribute.m b/contribute.m index f51f371..af50fc7 100644 --- a/contribute.m +++ b/contribute.m @@ -1,4 +1,4 @@ -function contribute(verbose) +function contribute(repoName, printLevel) % devTools % % PURPOSE: displays a menu and calls the respective subfunctions @@ -7,9 +7,18 @@ function contribute(verbose) % 2. Select an existing feature (branch) to work on. % 3. Publish a feature (branch). % 4. Delete a feature (branch). +% +% INPUT: +% +% printLevel: 0: minimal printout (default) +% 1: detailed printout (debug mode) global gitConf global gitCmd + global resetDevToolsFlag + global DEFAULTREPONAME + + resetDevToolsFlag = true; % retrieve the current directory currentDir = pwd; @@ -17,18 +26,29 @@ function contribute(verbose) % adding the src folder of the devTools addpath(genpath(fileparts(which(mfilename)))); - % check the system and set the configuration - checkSystem(mfilename); + % treatment of input arguments + if ~exist('repoName', 'var') + DEFAULTREPONAME = 'opencobra/cobratoolbox'; % set the default repository + repoName = DEFAULTREPONAME; + end - if nargin > 0 - if verbose - gitConf.verbose = verbose; - else - gitConf.verbose = false; + % soft reset if the repository name is different + if ~isempty(gitConf) + if ~strcmpi(repoName, [gitConf.remoteUserName '/' gitConf.remoteRepoName]) + resetDevTools(); end end - devToolsDir = fileparts(which('contribute.m')); + % check the system and set the configuration + if exist('printLevel', 'var') + checkSystem(mfilename, repoName, printLevel); + else + checkSystem(mfilename, repoName); + end + + finishup = onCleanup(@() resetDevTools()); + + devToolsDir = fileparts(which(mfilename)); % change to the directory of the devTools cd(devToolsDir); @@ -38,7 +58,7 @@ function contribute(verbose) fprintf(gitConf.launcher); - choice = input('\n (You can abort any process using CTRL-C)\n\n [1] Start a new feature (branch).\n [2] Select an existing feature (branch) to work on.\n [3] Publish a feature (branch).\n [4] Delete a feature (branch).\n [5] Update the fork.\n\n -> Please select what you want to do (enter the number): ', 's'); + choice = input('\n (You can abort any process using CTRL+C)\n\n [1] Start a new feature (branch).\n [2] Select an existing feature (branch) to work on.\n [3] Publish a feature (branch).\n [4] Delete a feature (branch).\n [5] Update the fork.\n\n -> Please select what you want to do (enter the number): ', 's'); choice = str2num(choice); @@ -69,7 +89,7 @@ function contribute(verbose) exitFlag = false; else % initialize the development tools - initDevTools(); + initDevTools(repoName); % change to the fork diretory cd(gitConf.fullForkDir); @@ -128,6 +148,9 @@ function contribute(verbose) end end + resetDevToolsFlag = false; + % change back to the current directory cd(currentDir); + end diff --git a/docs/.documenter.enc b/docs/.documenter.enc new file mode 100644 index 0000000..e69de29 diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..489d6fd --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,228 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " epub3 to make an epub3" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + @echo " dummy to check syntax errors of document sources" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + @echo "Generating list of suggestions for the websearch." + python generateJSONList.py + @echo + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MWE.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MWE.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/MWE" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/MWE" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: epub3 +epub3: + $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 + @echo + @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." + +.PHONY: dummy +dummy: + $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy + @echo + @echo "Build finished. Dummy builder generates no files." diff --git a/docs/generateJSONList.py b/docs/generateJSONList.py new file mode 100644 index 0000000..53f9038 --- /dev/null +++ b/docs/generateJSONList.py @@ -0,0 +1,44 @@ +import os +import json +import errno + +def mkdir_p(path): + try: + os.makedirs(path) + except OSError as exc: # Python >2.5 + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: + raise + + +def mkdir_p(path): + try: + os.makedirs(path) + except OSError as exc: # Python >2.5 + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: + raise + +def path_to_list(path): + d = [] + path_length = len(path) + print path_length, path + for root, directories, filenames in os.walk(path): + for filename in filenames: + print os.path.join('source', 'modules', root[path_length+1:], 'index.rst') + if filename[-2:] == '.m' and os.path.isfile(os.path.join('source', 'modules', root[path_length+1:], 'index.rst')): + website_url = os.path.join("modules", root[path_length+1:], "index.html") + website_url += "?highlight=" + filename[:-2] + website_url += "#" + '.'.join(['src'] + [filename[:-2]]) + d.append({'name': filename[:-2], + 'website_url': website_url}) + print root, filename + return d + +destination_dir = os.path.join('source', '_static', 'json') +mkdir_p(destination_dir) +with open(os.path.join(destination_dir, 'functions.json'), 'w') as f: + d = path_to_list('../src/.') + json.dump(d, f) diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..175c844 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,6 @@ +git+https://github.com/uni-lu/sphinx.git@develop#egg=sphinx +git+https://github.com/syarra/sphinxcontrib-matlabdomain#egg=sphinxcontrib-matlabdomain +sphinx_rtd_theme +git+https://github.com/uni-lu/sphinx_julia_theme.git@develop#egg=sphinx_julia_theme +git+https://github.com/syarra/Documenter.py@develop#egg=documenter +git+https://github.com/uni-lu/sphinxcontrib-napoleon.git@develop#egg=sphinxcontrib_napoleon diff --git a/docs/source/_static/browserconfig.xml b/docs/source/_static/browserconfig.xml new file mode 100644 index 0000000..efcaaf6 --- /dev/null +++ b/docs/source/_static/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #da532c + + + diff --git a/docs/source/_static/img/android-chrome-192x192.png b/docs/source/_static/img/android-chrome-192x192.png new file mode 100644 index 0000000..6bc6706 Binary files /dev/null and b/docs/source/_static/img/android-chrome-192x192.png differ diff --git a/docs/source/_static/img/android-chrome-384x384.png b/docs/source/_static/img/android-chrome-384x384.png new file mode 100644 index 0000000..7e97089 Binary files /dev/null and b/docs/source/_static/img/android-chrome-384x384.png differ diff --git a/docs/source/_static/img/apple-touch-icon.png b/docs/source/_static/img/apple-touch-icon.png new file mode 100644 index 0000000..fc8de68 Binary files /dev/null and b/docs/source/_static/img/apple-touch-icon.png differ diff --git a/docs/source/_static/img/favicon-16x16.png b/docs/source/_static/img/favicon-16x16.png new file mode 100644 index 0000000..a9da3d2 Binary files /dev/null and b/docs/source/_static/img/favicon-16x16.png differ diff --git a/docs/source/_static/img/favicon-32x32.png b/docs/source/_static/img/favicon-32x32.png new file mode 100644 index 0000000..1d6637e Binary files /dev/null and b/docs/source/_static/img/favicon-32x32.png differ diff --git a/docs/source/_static/img/favicon.ico b/docs/source/_static/img/favicon.ico new file mode 100644 index 0000000..86ba614 Binary files /dev/null and b/docs/source/_static/img/favicon.ico differ diff --git a/assets/devTools_logo.png b/docs/source/_static/img/logo_devTools.png similarity index 100% rename from assets/devTools_logo.png rename to docs/source/_static/img/logo_devTools.png diff --git a/docs/source/_static/img/mstile-150x150.png b/docs/source/_static/img/mstile-150x150.png new file mode 100644 index 0000000..1a5cebd Binary files /dev/null and b/docs/source/_static/img/mstile-150x150.png differ diff --git a/docs/source/_static/img/safari-pinned-tab.svg b/docs/source/_static/img/safari-pinned-tab.svg new file mode 100644 index 0000000..c686f93 --- /dev/null +++ b/docs/source/_static/img/safari-pinned-tab.svg @@ -0,0 +1,37 @@ + + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + + + diff --git a/docs/source/_static/json/manifest.json b/docs/source/_static/json/manifest.json new file mode 100644 index 0000000..870e24e --- /dev/null +++ b/docs/source/_static/json/manifest.json @@ -0,0 +1,18 @@ +{ + "name": "", + "icons": [ + { + "src": "../img/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "../img/android-chrome-384x384.png", + "sizes": "384x384", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/docs/source/cite.rst b/docs/source/cite.rst new file mode 100644 index 0000000..a8af629 --- /dev/null +++ b/docs/source/cite.rst @@ -0,0 +1,62 @@ +How to cite +=========== + +.. include:: ../../README.rst + :start-after: begin-how-to-cite-marker + :end-before: end-how-to-cite-marker + + +.. |macos| raw:: html + + macOS + + +.. |linux| raw:: html + + linux + + +.. |windows| raw:: html + + windows + + +.. |warning| raw:: html + + warning + + +.. |matlab| raw:: html + + matlab + + +.. |tada| raw:: html + + tada + + +.. |thumbsup| raw:: html + + thumbsup + + +.. |bulb| raw:: html + + bulb + + +.. |tutorials| raw:: html + + + + +.. |latest| raw:: html + + + + +.. |forum| raw:: html + + + diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..70e5355 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +# +# Documentation build configuration file, created by +# sphinx-quickstart on Fri Nov 18 11:12:41 2016. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. + +import os +import sys + +sys.path.append('sphinxext') +from github_linkcode import github_linkcode_resolve + + +sys.path.insert(0, os.path.abspath(os.path.join('..', '..', '..'))) +# sys.path.insert(0, os.path.abspath('.')) + +# tell Sphinx matlab extension where to find matlab code. +matlab_src_dir = os.path.abspath(os.path.join('..', '..')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinxcontrib.napoleon', + 'sphinxcontrib.matlab', + 'github', + 'sphinx.ext.mathjax', + 'sphinx.ext.linkcode', + 'sphinxcontrib.fulltoc'] + +mathjax_path = 'https://cdn.rawgit.com/mathjax/MathJax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML' + +def linkcode_resolve(domain, info): + return github_linkcode_resolve( + domain=domain, + info=info, + allowed_module_names=['src'], + github_org_id='opencobra', + github_repo_id='MATLAB.devTools', + branch='master', + source_prefix='') + + +# autodoc_member_order='groupwise' +primary_domain = 'mat' + +# remove path in function names +add_module_names = False + +# Add any paths that contain templates here, relative to this directory. +# templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +source_suffix = ['.rst'] + +# The encoding of source files. +# +source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'contents' + +# General information about the project. +project = u'MATLAB.devTools' +copyright = u'2017-2018, the MATLAB.devTools developers' +author = u'The MATLAB.devTools developers' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'0.1' +# The full version, including alpha/beta/rc tags. +release = u'0.1.1' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None +conf_py_path = os.getcwd() +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# +# today = '' +# +# Else, today_fmt is used as the format for a strftime call. +# +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +# +# default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +# +# add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +html_theme = "sphinx_julia_theme" + +import sphinx_julia_theme +import sphinx_rtd_theme + +html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), + sphinx_julia_theme.get_theme_dir()] +print html_theme_path +html_sidebars = sphinx_julia_theme.default_sidebars() + +# shutil.copy() + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +html_theme_options = {'display_version': False} + +html_context = {'conf_py_path': os.path.join(os.sep, 'docs', 'source', ''), + 'github_user': 'opencobra', + 'github_repo': 'MATLAB.devTools', + 'github_version': 'master', + 'logo': 'img/logo_devTools.png', + 'favicon_apple_touch': 'img/apple-touch-icon.png', + 'favicon32x32': 'img/favicon-32x32.png', + 'favicon16x16': 'img/favicon-16x16.png', + 'favicon_safari_pinned_tab': 'img/safari-pinned-tab.svg', + 'manifest': 'json/manifest.json', + 'browserconfig': 'browserconfig.xml', + 'theme_logo_only': False, + 'show_source': False} +# 'display_github': True} +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. +# " v documentation" by default. +# +html_title = u'MATLAB.devTools' + +# A shorter title for the navigation bar. Default is the same as html_title. +# +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# +html_logo = '_static/img/logo_devTools.png' + +# The name of an image file (relative to this directory) to use as a favicon of +# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +# +html_favicon = '_static/img/favicon.ico' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +# +# html_extra_path = [] + +# If not None, a 'Last updated on:' timestamp is inserted at every page +# bottom, using the given strftime format. +# The empty string is equivalent to '%b %d, %Y'. +# +# html_last_updated_fmt = None + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# +# html_sidebars = {'index': 'indexsidebar.html'} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# +# html_index = 'index.html' +# html_additional_pages = {'index': 'index.html'} + +# If false, no module index is generated. +# +# html_domain_indices = True + +# If false, no index is generated. +# +# html_use_index = False + +# If true, the index is split into individual pages for each letter. +# +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh' +# +# html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# 'ja' uses this config value. +# 'zh' user can custom change `jieba` dictionary path. +# +# html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +# +# html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'MATLAB.devToolsDoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'MATLAB.devTools.tex', u'The MATLAB.devTools Documentation', + u'The MATLAB.devTools developers', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# +# latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# +# latex_use_parts = False + +# If true, show page references after internal links. +# +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# +# latex_appendices = [] + +# It false, will not define \strong, \code, itleref, \crossref ... but only +# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added +# packages. +# +# latex_keep_old_macro_names = True + +# If false, no module index is generated. +# +# latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'MATLAB.devTools', u'The MATLAB.devTools Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +# +# man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'MATLAB.devTools', u'The MATLAB.devTools Documentation', + author, 'MATLAB.devTools', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +# +# texinfo_appendices = [] + +# If false, no module index is generated. +# +# texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# +# texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +# +# texinfo_no_detailmenu = False diff --git a/docs/source/contents.rst b/docs/source/contents.rst new file mode 100644 index 0000000..7da0986 --- /dev/null +++ b/docs/source/contents.rst @@ -0,0 +1,15 @@ +MATLAB.devTools +=============== + +.. toctree:: + :maxdepth: 2 + + Home + installation + getstarted + contribute + modules/index + faq + troubleshooting + cite + funding diff --git a/docs/source/contr_cobratoolbox.rst b/docs/source/contr_cobratoolbox.rst new file mode 100644 index 0000000..fa53b5b --- /dev/null +++ b/docs/source/contr_cobratoolbox.rst @@ -0,0 +1,213 @@ +The COBRA Toolbox +^^^^^^^^^^^^^^^^^ + +|asciicast| + +.. include:: ../../README.rst + :start-after: begin-screencast-marker + :end-before: end-screencast-marker + +Introduction +------------ + +A comprehensive code base such as the COBRA Toolbox evolves constantly. The +open-source community is very active, and collaborators submit their +contributions frequently. The more a new feature or bug fix is interlinked with +existing functions, the higher the risk of a new addition breaking instantly +code that is heavily used on a daily basis. In order to decrease this risk, a +continuous integration setup interlinked with the version control system git +has been set up. A git-tracked repository is essentially a folder with code or +other documents of which all incremental changes are tracked by date and user. + +Any incremental changes to the code are called commits. The main advantage of +git over other version control systems is the availability of branches. In +simple terms, a branch contains a sequence of incremental changes to the code. +A branch is also commonly referred to as a feature. Consequently, a +contribution generally consists of several commits on a branch. + +Contributing to the COBRA Toolbox is straightforward. As a contributor to the +COBRA Toolbox is likely more familiar with MATLAB than with the internal +mechanics of git, the `MATLAB.devTools` have been developed specifically +to contribute to a git-tracked repository located on the Github server. In +Figure 6, an overview of the two online repositories as well as their local +copies is given. There are two ways of using the COBRA Toolbox, which depends +on the type of user. A regular user might only want to use the opencobra +repository and enjoy stability (option A), whereas more advanced users might +want to develop their own features and actively make contributions to the +opencobra repository (option B). + +|branchModel| + + - **Option A** The `opencobra/cobratoolbox `_ repository is a + public repository that is read-only. Once the opencobra repository has been + installed in the folder `cobratoolbox`, all branches + (including ``master`` and ``develop``) are available locally. In the local directory + `cobratoolbox` folder, the user has read and write access, but cannot push eventual + changes back to the opencobra repository. It is the default and stable ``master`` + branch only that should be used. The local copy located in the cobratoolbox + directory can be updated (both branches). + + - **Option B** In order to make changes to the + opencobra repository, or, in other words, contribute, you must obtain your own + personal copy first. You must register on the `Github website `_ in order to obtain a username. First, click on the button FORK at the top + right corner of the official `opencobra/cobratoolbox `_ repository website + in order to create a personal copy + (or fork) with write and read access of the opencobra repository. This copy is + accessible under `https://github.com//cobratoolbox`, where `` is + your Github username. In the + `fork-cobratoolbox` folder, other user specific branches may exist in addition to + the ``master`` and ``develop`` branches. + +After initialisation of the MATLAB.devTools, the user and developer may have two +folders: a ``cobratoolbox`` folder with the stable ``master`` branch checked out, and a +``fork-cobratoolbox`` folder with the ``develop`` branch checked out. Detailed +instructions for troubleshooting and/or contributing to the COBRA Toolbox using +the terminal (or shell) are provided :ref:`here `. + +After the official opencobra version of the COBRA Toolbox has been installed, +it is possible to install the MATLAB.devTools from within MATLAB: + +.. code:: console + + >> installDevTools + +With this command, the directory MATLAB.devTools is created next to the +cobratoolbox installation directory. The MATLAB.devTools can also be installed +from the terminal (or shell): + +.. code:: console + + $ git clone git@github.com:opencobra/MATLAB.devTools + +|warning| A working internet connection is required and git and curl must be +installed. Installation instructions are provided on the main repository page +of the MATLAB.devTools. A valid passphrase-less SSH key must be set in the +Github account settings in order to contribute without entering a password +while securely communicating with the Github server. + +Start a new contribution +------------------------ + +The MATLAB.devTools are configured on the fly or whenever the configuration +details are not present. The first time a user runs contribute, the personal +repository (fork) is downloaded (cloned) into a new folder named +`fork-cobratoolbox` at the location specified by the user. In this local folder, +both ``master`` and ``develop`` branches exist, but it is the ``develop`` branch that is +automatically selected (checked out). Any new contributions are derived from +the develop branch. Initialising a contribution using the MATLAB.devTools is +straightforward. In MATLAB, type: + +.. code:: matlab + + >> contribute % then select procedure [1] + +If the MATLAB.devTools are already configured, procedure [1] updates the fork +(if necessary) and initialises a new branch with a name requested during the +process. Once the contribution is initialised, files can be added, modified or +deleted in the `fork-cobratoolbox` folder. A contribution is successfully +initialised when the user is presented with a brief summary of configuration +details. Instructions on how to proceed are also provided. + +|warning| The location of the fork must be specified as the root directory. +There will be a warning issued if the path already contains another git-tracked +repository. + +Continue an existing contribution +--------------------------------- + +An existing contribution can be continued after a while. This step is +particularly important in order to retrieve all changes that have been made to +the opencobra repository in the meantime. + +.. code:: matlab + + >> contribute % then select procedure [2] + +Procedure ``[2]`` pulls all changes from the opencobra repository, and rebases the +existing contribution. In other words, existing commits are shifted forward and +placed after all commits made on the develop branch of the opencobra +repository. + +|warning| Before attempting to continue working on an existing +feature, make sure that you published your commits. + +Publish a contribution +----------------------- + +Publishing a contribution means uploading the incremental code changes to the +fork. The changes are available in public, but not yet available in the +opencobra repository. A contribution may only be accepted in the official +repository once a pull request has been submitted. It is not necessary to open +a pull request if you want to simply upload your contribution to your fork. + +.. code:: matlab + + >> contribute % then select procedure [3] + +When running procedure ``[3]``, you have two options: + +- **Option A** Simple contribution without opening a pull request: All changes + to the code are individually listed and the user is asked explicitly which + changes shall be added to the commit. Once all changes have been added, a + commit message must be entered. Upon confirmation, the changes are pushed to + the online fork automatically. + +- **Option B** Publishing and opening a pull request: The procedure for + submitting a pull request is the same as option (A) with the difference that + when selecting to open a pull request, a link is provided that leads to a + pre-configured website according to the contributing guidelines. The pull + request is then one click away. + +|warning| After following procedures ``[1]`` and ``[2]``, all changes should be +published using procedure ``[3]`` before stopping to work on that contribution. +When following procedure ``[3]``, the incremental changes are uploaded to the +remote server. It is advised to publish often, and make small incremental +changes to the code. There is no need for opening a pull request immediately +(option **A**) if there are more changes to be made. A pull request may be opened +at any time, even manually directly from the Github website. + +Deleting a contribution +----------------------- + +If a contribution has been merged into the develop branch of the opencobra +repository (accepted pull request), the contribution (feature or branch) can be +safely deleted both locally and remotely on the fork by running contribute and +selecting procedure ``[4]``. + +Note that deleting a contribution deletes all the changes that have been made +on that feature (branch). It is not possible to selectively delete a commit +using the MATLAB.devTools. Instead, create a new branch by following procedure +``[1]``, and follow the instructions to cherry-pick (see +:ref:`troubleshooting`). + +|warning| Make sure that your changes are either merged or saved locally if you +need them. Once procedure ``[4]`` is concluded, all changes on the deleted +branch are removed, both locally and remotely. No commits can be recovered. + +Update your fork +---------------- + +It is sometimes useful to simply update the fork without starting a new +contribution. The local fork can be updated using procedure ``[5]`` of the +contribute menu. + +.. code:: matlab + + >> contribute % then select procedure [5] + +Before updating your fork, make sure that no changes are present in the local +directory `fork-cobratoolbox`. You can do so by typing: + +.. code:: matlab + + >> checkStatus + +If there are changes listed, publish them by selecting procedure ``[3]`` of the +contribute menu. + +.. |branchModel| image:: https://prince.lcsb.uni.lu/img/figure6.png + +.. include:: ../../README.rst + :start-after: begin-icon-marker + :end-before: end-icon-marker + diff --git a/docs/source/contr_cobratutorials.rst b/docs/source/contr_cobratutorials.rst new file mode 100644 index 0000000..da33a76 --- /dev/null +++ b/docs/source/contr_cobratutorials.rst @@ -0,0 +1,9 @@ +COBRA.tutorials +^^^^^^^^^^^^^^^ + +.. include:: ../../README.rst + :start-after: begin-contribute-cobratutorials-marker + :end-before: end-contribute-cobratutorials-marker + +In case of troubleshooting, please refer `this <>`__ section. + diff --git a/docs/source/contr_otherrepo.rst b/docs/source/contr_otherrepo.rst new file mode 100644 index 0000000..18d0643 --- /dev/null +++ b/docs/source/contr_otherrepo.rst @@ -0,0 +1,11 @@ +Other repository +^^^^^^^^^^^^^^^^ + +.. include:: ../../README.rst + :start-after: begin-contribute-other-repo-marker + :end-before: end-contribute-other-repo-marker + +.. include:: ../../README.rst + :start-after: begin-icon-marker + :end-before: end-icon-marker + diff --git a/docs/source/contribute.rst b/docs/source/contribute.rst new file mode 100644 index 0000000..945d50d --- /dev/null +++ b/docs/source/contribute.rst @@ -0,0 +1,8 @@ +.. _contribute: + +How to configure and use +======================== + +.. include:: contr_cobratoolbox.rst +.. include:: contr_cobratutorials.rst +.. include:: contr_otherrepo.rst diff --git a/docs/source/faq.rst b/docs/source/faq.rst new file mode 100644 index 0000000..2cf3c72 --- /dev/null +++ b/docs/source/faq.rst @@ -0,0 +1,111 @@ +.. _faq: + +Frequently Asked Questions (FAQ) +================================ + +General questions +----------------- + +How should I name my contribution? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Initiate a contribution per theme/topic/feature/bug fix that you work +on. Don’t mix features and think of an explicit name, i.e. +``bug-fix-function1`` or ``add-tests-function2``. Avoid generic names, +such as ``my-great-feature`` or ``fix`` or ``contribution-myName``. + +How can I check the history of a file? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can check the history of a file by typing in MATLAB: + +.. code:: matlab + + >> history('fileName.m') + +How do I submit a Pull Request (PR)? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Once you submit your contribution (menu option [3]), you will be +presented with a link that leads you directly to the pull request (PR). + +Print more detailed debugging information (verbose) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you encounter a problem, or suspect that something is not behaving +properly, please run: + +.. code:: matlab + + >> contribute(1) + +and follow the process as normally. This will set ``printLevel = 1``. +You can also set permanently ``gitConf.printLevel = 1;`` in +``assets/confDevTools.m``. + + +Technical questions +------------------- + +I receive a ``Permission denied`` error. What can I do? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You may encounter the following error: + +:: + + Permission denied (publickey) + fatal: could not read from the repository. + + Please make sure you have the correct access rights + and the repository exists. + +This error can have multiple reasons, but most likely, the SSH key is +not configured properly. Please follow the `configuration +instructions `__ +carefully. + +Another source of this error may be that you have set a passphrase when +generating the SSH key. Please leave the passphrase empty when +generating the SSH key. + +Mismatch of the version of ``openSSL`` (Linux) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You might be in the situation that you receive the following error: + +:: + + OpenSSL version mismatch. Built against 1000207f, you have 100010bf + +In that case, you should run the following command: + +:: + + sudo mv /bin/glnxa64/libcrypto.so.1.0.0 /bin/glnxa64/libcrypto.so.1.0.0_bk + +where ```` corresponds to the installation of +``MATLAB``, e.g., ``/usr/local/MATLAB/R2016b`` + +Resolve unexpected behavior - reset +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you encounter unexpected behavior, please try to reset the +``MATLAB.devTools`` using the ``resetDevTools`` functionality. + +.. include:: ../../README.rst + :start-after: begin-reset-marker + :end-before: end-reset-marker + +If you have files or changes that appear and would like to reset your +local fork (without re-cloning) again, type: + +.. code:: matlab + + >> resetLocalFork + +How can I abort a process? +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can abort any process using ``CTRL+C`` (hit ``CTRL`` and ``C`` on +your keyboard). diff --git a/docs/source/funding.rst b/docs/source/funding.rst new file mode 100644 index 0000000..3449415 --- /dev/null +++ b/docs/source/funding.rst @@ -0,0 +1,58 @@ +Funding +======= + +.. raw:: html + + +
+ + + + + + +
+
+
+
+
+ National Centre of Excellence in Research (NCER) on Parkinson’s disease. +
+ + + + + + +
+
+
+ U.S. Department of Energy, Offices of Advanced Scientific Computing Research and the Biological and Environmental Research as part of the Scientific Discovery Through Advanced Computing program, grant no. DE-SC0010429 +
+ +
+

+

+ Fonds National de la Recherche grant O16/11402054 and the Luxembourg National Research Fund (FNR) ATTRACT program grant (FNR/A12/01). +
+

+ +

diff --git a/docs/source/getstarted.rst b/docs/source/getstarted.rst new file mode 100644 index 0000000..b69b1a8 --- /dev/null +++ b/docs/source/getstarted.rst @@ -0,0 +1,11 @@ +How to get started +================== + +.. include:: ../../README.rst + :start-after: begin-getstarted-marker + :end-before: end-getstarted-marker + +.. include:: ../../README.rst + :start-after: begin-icon-marker + :end-before: end-icon-marker + diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..11386cb --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,27 @@ +.. _index: + +.. image:: _static/img/logo_devTools.png + :align: center + :width: 160px + +MATLAB.devTools +=============== + +.. rst-class:: under-title + +MATLAB.devTools - Contribute the smart way + +.. raw:: html + + + +
+ View MATLAB.devTools source code on . +
+ +.. include:: ../../README.rst + :start-after: begin-description-marker + :end-before: end-description-marker + diff --git a/docs/source/installation.rst b/docs/source/installation.rst new file mode 100644 index 0000000..36534d5 --- /dev/null +++ b/docs/source/installation.rst @@ -0,0 +1,19 @@ +.. _installation: + +Installation +============ + +.. include:: prerequisites.rst + + +Installation +------------ + +.. include:: ../../README.rst + :start-after: begin-installation-marker + :end-before: end-installation-marker + +.. include:: ../../README.rst + :start-after: begin-icon-marker + :end-before: end-icon-marker + diff --git a/docs/source/modules/index.rst b/docs/source/modules/index.rst new file mode 100644 index 0000000..d475b7b --- /dev/null +++ b/docs/source/modules/index.rst @@ -0,0 +1,8 @@ +.. _modules_functions: + +Functions +--------- + +.. automodule:: src + :members: + diff --git a/docs/source/prerequisites.rst b/docs/source/prerequisites.rst new file mode 100644 index 0000000..cd32dbb --- /dev/null +++ b/docs/source/prerequisites.rst @@ -0,0 +1,134 @@ +Pre-requisites +-------------- + +GitHub SSH configuration +^^^^^^^^^^^^^^^^^^^^^^^^ + +You have to register the SSH key of each computer that you are planning +to use the ``MATLAB.devTools`` on. + +- **Check if you already have an SSH key:** + +.. code:: console + + $ ls -al ~/.ssh + +If there is a file with an extension ``.pub``, you already have an SSH +key. Now, you have to **add your SSH key to Github**. More help is +`here `__. + +- **Generate the SSH key on your computer:** If you don’t have yet an + SSH key (see previous step), you have to generate one (more help is + `here `__): + +.. code:: console + + $ ssh-keygen -t rsa -C "first.last@server.com" + + Leave the passphrase empty when generating the SSH key. + +- **Add the SSH** to `your Github + account `__ by following the steps + `here `__. + +Can I check if everything is properly set up before I start? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Please ensure that you have a working ``MATLAB`` installation. + +You can check if you have a working installation of ``git`` by typing in +the ``Terminal`` (on ``linux`` and ``macOS``) or ``cmd`` (in +``Windows``, not ``Git Bash``): + +.. code:: bash + + $ git --version + +If installed properly, this will return ``git version 2.13.1 [...]`` or +similar with another version number. + +You can then check if your ``git`` is properly configured by typing in +the terminal (or GUI Bash): + +.. code:: bash + + $ git config --get user.github-username + +which will return your Github username if everything is properly set up. +Similarly, check the configured email by typing in the terminal (or GUI +Bash): + +.. code:: bash + + $ git config --get user.email + +You can check if you have a working installation of ``curl`` by typing +in the terminal (``cmd`` on Windows, not ``Git Bash``): + +.. code:: bash + + $ curl --version + +which will return ``curl 7.51.0 [...]`` or similar with another version +number if installed properly. + +System configuration +^^^^^^^^^^^^^^^^^^^^ + +You must have ``git`` and ``curl`` installed. Please also ensure that +you have ``MATLAB`` +`installed `__. + +**Windows** + +Please download the ``git`` tools for Windows from +`here `__. During the installation +process, please ensure that you select **Use Git Bash and optional Unix +tools from the Windows Command prompt**. In addition, please make sure +that you select **Checkout as-is, commit Unix-style line endings**. + +|windows0| |windows1| + +**Linux (Ubuntu or Debian)** + +.. code:: bash + + $ sudo apt-get install git-all curl + +**macOS** + +In order to install ``git``, install the `Xcode Command Line +Tools `__. +For ``curl``, follow the instructions +`here `__. + +Github and local ``git`` configuration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you don’t have a GitHub account, please sign up +`here `__. For the very first time, you must +**fork** the repository of The COBRA Toolbox. Browse to the `original +repository `__ and click on +the button . + +On **Linux (Ubuntu)** or **macOS**, start the terminal (or any other +shell). On **Windows**, start ``GUI Bash``. Then type + +.. code:: bash + + $ git config --global user.github-username "yourGitHubUsername" + $ git config --global user.email "first.last@server.com" + +Please replace ``"yourGitHubUsername"`` and ``"first.last@server.com"`` +with your respective credentials. + +.. |windows0| image:: https://prince.lcsb.uni.lu/img/installation_git_windows_0.png + :width: 280px + +.. |windows1| image:: https://prince.lcsb.uni.lu/img/installation_git_windows_1.png + :width: 280px + +.. include:: ../../README.rst + :start-after: begin-icon-marker + :end-before: end-icon-marker + diff --git a/docs/source/sphinxext/__init__.py b/docs/source/sphinxext/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/docs/source/sphinxext/github_linkcode.py b/docs/source/sphinxext/github_linkcode.py new file mode 100644 index 0000000..dfe9e61 --- /dev/null +++ b/docs/source/sphinxext/github_linkcode.py @@ -0,0 +1,243 @@ +"""Sphinx extension to link to source code on GitHub. + +This links to source code for modules, classes, etc. to the correct line on +GitHub. This prevents having to bundle the source code along with the +documentation, and better ties everything together. + + +Setup +===== + +To use this, you'll need to import the module and define your own +:py:func:`linkcode_resolve` in your :file:`conf.py`:: + + from beanbag_docutils.sphinx.ext.github import github_linkcode_resolve + + extensions = [ + ... + 'sphinx.ext.linkcode', + ... + ] + + def linkcode_resolve(domain, info): + return github_linkcode_resolve( + domain=domain, + info=info, + allowed_module_names=['mymodule'], + github_org_id='myorg', + github_repo_id='myrepo', + branch='master', + source_prefix='src/') + +``source_prefix`` and ``allowed_module_names`` are optional. See the +docs for :py:func:`github_linkcode_resolve` for more information. +""" + +from __future__ import unicode_literals + +import inspect +import re +import subprocess +import sys + + +GIT_BRANCH_CONTAINS_RE = re.compile(r'^\s*([^\s]+)\s+([0-9a-f]+)\s.*') + + +_head_ref = None + + +def _run_git(cmd): + """Run git with the given arguments, returning the output. + + Args: + cmd (list of unicode): + A list of arguments to pass to :command:`git`. + + Returns: + str: + The resulting output from the command. + + Raises: + subprocess.CalledProcessError: + Error calling into git. + """ + p = subprocess.Popen(['git'] + cmd, stdout=subprocess.PIPE) + output, error = p.communicate() + ret_code = p.poll() + + if ret_code: + raise subprocess.CalledProcessError(ret_code, 'git') + + return output + + +def _git_get_nearest_tracking_branch(merge_base, remote='origin'): + """Return the nearest tracking branch for the given Git repository. + + Args: + merge_base (unicode): + The merge base used to locate the nearest tracking branch. + + remote (origin, optional): + The remote name. + + Returns: + unicode: + The nearest tracking branch, or ``None`` if not found. + """ + try: + _run_git(['fetch', 'origin', '%s:%s' % (merge_base, merge_base)]) + except Exception: + # Ignore, as we may already have this. Hopefully it won't fail later. + pass + + lines = _run_git(['branch', '-rv', '--contains', merge_base]).splitlines() + + remote_prefix = '%s/' % remote + best_distance = None + best_ref_name = None + + for line in lines: + m = GIT_BRANCH_CONTAINS_RE.match(line.strip()) + + if m: + ref_name = m.group(1) + sha = m.group(2) + + if (ref_name.startswith(remote_prefix) and + not ref_name.endswith('/HEAD')): + + distance = len(_run_git(['log', + '--pretty=format:%%H', + '...%s' % sha]).splitlines()) + + if best_distance is None or distance < best_distance: + best_distance = distance + best_ref_name = ref_name + + if best_ref_name and best_ref_name.startswith(remote_prefix): + # Strip away the remote. + best_ref_name = best_ref_name[len(remote_prefix):] + + return best_ref_name + + +def _get_git_doc_ref(branch): + """Return the commit SHA used for linking to source code on GitHub. + + The commit SHA will be cached for future lookups. + + Args: + branch (unicode): + The branch to use as a merge base. + + Returns: + unicode: + The commit SHA used for any links, if found, or ``None`` if not. + """ + global _head_ref + + if not _head_ref: + try: + tracking_branch = _git_get_nearest_tracking_branch(branch) + _head_ref = _run_git(['rev-parse', tracking_branch]).strip() + except subprocess.CalledProcessError: + _head_ref = None + + return _head_ref + + +def github_linkcode_resolve(domain, info, github_org_id, github_repo_id, + branch, source_prefix='', allowed_module_names=[]): + """Return a link to the source on GitHub for the given autodoc info. + + This takes some basic information on the GitHub project, branch, and + what modules are considered acceptable, and generates a link to the + approprite line on the GitHub repository browser for the class, function, + variable, or other object. + + Args: + domain (unicode): + The autodoc domain being processed. This only accepts "py", and + comes from the original :py:func:`linkcode_resolve` call. + + info (dict): + Information on the item being linked to. This comes from the + original :py:func:`linkcode_resolve` call. + + github_org_id (unicode): + The GitHub organization ID. + + github_repo_id (unicode): + The GitHub repository ID. + + branch (unicode): + The branch used as a merge base to find the appropriate commit + to link to. Callers may want to compute this off of the version + number of the project, or some other information. + + source_prefix (unicode, optional): + A prefix for any linked filename, in case the module is not at + the top of the source tree. + + allowed_module_names (list of unicode, optional): + The list of top-level module names considered valid for links. + If provided, links will only be generated if residing somewhere + in one of the provided module names. + """ + module_name = info['module'] + + # print domain != 'mat' + # print not module_name + # print module_name.split('.')[0] + # print allowed_module_names + # print (allowed_module_names and + # module_name.split('.')[0] not in allowed_module_names) + if (domain != 'mat' or + not module_name or + (allowed_module_names and + module_name.split('.')[0] not in allowed_module_names)): + # These aren't the modules you're looking for. + return None + + # Grab the name of the source file. + filename = module_name.replace('.', '/') + '/' + info['fullname'] + '.m' + + # Grab the module referenced in the docs. + submod = sys.modules.get(module_name) + + if submod is None: + return None + + # Split that, trying to find the module at the very tail of the module + # path. + obj = submod + + for part in info['fullname'].split('.'): + try: + obj = getattr(obj, part) + except: + return None + + # Find the line number of the thing being documented. + try: + linenum = inspect.findsource(obj)[1] + except: + linenum = None + + # Build a reference for the line number in GitHub. + if linenum: + linespec = '#L%d' % (linenum + 1) + else: + linespec = '' + + # Get the branch/tag/commit to link to. + ref = _get_git_doc_ref(branch) or branch + # print "branch: ", branch + # print ('https://github.com/%s/%s/blob/%s/%s%s%s' + # % (github_org_id, github_repo_id, ref, source_prefix, + # filename, linespec)) + return ('https://github.com/%s/%s/blob/%s/%s%s%s' + % (github_org_id, github_repo_id, ref, source_prefix, + filename, linespec)) diff --git a/docs/source/troubleshooting.rst b/docs/source/troubleshooting.rst new file mode 100644 index 0000000..17eb424 --- /dev/null +++ b/docs/source/troubleshooting.rst @@ -0,0 +1,7 @@ +.. _troubleshooting: + +Troubleshooting +=============== + +.. include:: troubleshooting/cobratoolbox.rst +.. include:: troubleshooting/cobratutorials.rst diff --git a/docs/source/troubleshooting/cobratoolbox.rst b/docs/source/troubleshooting/cobratoolbox.rst new file mode 100644 index 0000000..ff51612 --- /dev/null +++ b/docs/source/troubleshooting/cobratoolbox.rst @@ -0,0 +1,224 @@ +The COBRA Toolbox +^^^^^^^^^^^^^^^^^ + +|warning| This section is tailored to users who feel comfortable using +the terminal (or shell). It is recommended for other users +to follow :ref:`these instructions `. + +|warning| A Github account is required and `git` must be installed. You also +must already have forked the `opencobra/cobratoolbox +`__ repository by clicking on +the fork button on the main `opencobra/cobratoolbox +`__ repository page. + +Development scheme +------------------ + +The repository of the COBRA Toolbox is version controlled with the open-source +standard ``git`` on the public code development site `github.com +`__. Any incremental change to the code is wrapped in a +commit, tagged with a specific tag (called SHA1), a commit message, and author +information, such as the email address and the user name. Contributions to the +COBRA Toolbox are consequently commits that are made on branches. + +The development scheme adopted in the repository of the COBRA Toolbox has two +branches: a `master` and a `develop` branch. The stable branch is the `master` +branch, while it is the `develop` branch that includes all new features and to +which new contributions are merged. Contributions are submitted for review and +testing through pull requests, the `git` standard. The `develop` branch is +regularly merged into the `master` branch once testing is concluded. + +The development scheme has been adopted for obvious reasons: the COBRA Toolbox +is heavily used on a daily basis, while the development community is active. +The key advantage of this setup is that developers can work on the next stable +release, while users can enjoy a stable version. Developers and users are +consequently working on the same code base without interfering. Understanding +the concept of branches is key to submitting hassle-free pull requests and +starting to contribute using `git`. + +Clone the fork and update the submodules +---------------------------------------- + +|warning| Please note the following: + + - The following commands should only be run from the terminal (or the shell). + - An SSH key must be set in your Github account settings. + + In order to get started, clone the forked repository: + +.. code:: console + + $ git clone git@github.com:/cobratoolbox.git fork-cobratoolbox + +This will create a folder called fork-cobratoolbox. Make sure to replace +`` with your Github username. Any of the following commands are meant +to be run from within the folder of the fork called `fork-cobratoolbox`. + +.. code:: console + + $ cd fork-cobratoolbox + +In order to complete the cloned repository with external code, it is +recommended to clone all submodules: + +.. code:: console + + $ git submodule update --init + +Configure the remotes +--------------------- + +Note that your fork is a copy of the `opencobra/cobratoolbox +`__ repository and is not +automatically updated. As such, you have to configure the address of the +`opencobra/cobratoolbox `__ +repository: + +.. code:: console + + $ git remote add upstream git@github.com:opencobra/cobratoolbox.git + +Now, there are two addresses (also called remotes) configured: `origin` and +`upstream`. You can verify this by typing: + +.. code:: console + + $ git remote -v + +In order to update your fork, run the following commands: + +.. code:: console + + $ git fetch upstream + +First, update the `master` branch: + +.. code:: console + + $ git checkout master # checkout the branch locally + $ git merge upstream/master # merge the changes from the upstream repository + $ git push origin master # push the changes to the branch of the fork + +Then, update the `develop` branch: + +.. code:: console + + $ git checkout develop # checkout the branch + $ git merge upstream/develop # merge the changes on the branch from the upstream repository + $ git push origin develop # push the changes to the branch of the fork + +|warning| Should the step fail to checkout the develop branch, you should +create the develop branch first based on the `develop` branch of the upstream +repository: + +.. code:: console + + $ git checkout -b develop upstream/develop + +Then, you can proceed normally. + +Create a contribution and submit a pull request +----------------------------------------------- + +Now, as the fork is up-to-date with the upstream repository, start a new +contribution. A new contribution must be made on a new branch, that originates +from the `develop` branch. Create the new branch: + +.. code:: console + + $ git checkout -b develop + +Now, you can make changes in the folder `fork-cobratoolbox`. Once you are done +making changes, you can contribute the files. An important command that lists +all changes is to retrieve the repository status: + +.. code:: console + + $ git status + +A list is displayed with new, modified, and deleted files. You can add the changes (even deletions) by +adding the file: + +.. code:: console + + $ git add . + +|warning| Contrary to what is sometimes provided as a shortcut, it is not +advised to add all files all at once using as this command will add all files, +even hidden files and binaries. + +.. code:: console + + $ git add . # bad practice + +Then, commit the changes by setting a commit message : + +.. code:: console + + $ git commit -m "" + +Finally, push your commit to Github: + +.. code:: console + + $ git push origin + +You should then see your commit online, and if ready, you can open a +pull request. You can select your branch in the dropdown menu and list all +commits by clicking on `commits`. + +Continue working on your branch after a while (rebase) +------------------------------------------------------ + +If there have been major changes or if you want to continue working on a branch +after a while, it is recommended to do a rebase. In simple terms, rebasing your +branch shifts your commits to the top of the branch and includes all changes +from the upstream repository. Before doing so, make sure that you do not have +any uncommitted or local changes (git status). + +.. code:: console + + $ git checkout develop + $ git fetch upstream + $ git merge upstream/develop + $ git submodule update + $ git checkout + $ git rebase develop + +If you do not have any conflicts, you should see messages showing that your +changes have been applied. If however there are conflicts, it is advised to +use a merge tool such as `kdiff3`. In order to install a merge tool or abort +the rebase process, type: + +.. code:: console + + $ git rebase --abort + +In order to have the changes on `` reflected in the online +repository, push the changes with force. Pushing with force is required as the +history of the branch has been rewritten during rebase. + +.. code:: console + + $ git push --force + +Selectively use a commit on your branch (cherry-pick) +----------------------------------------------------- + +Imagine having two branches called `` and ``. On branch +`` is a commit with a SHA1 that you need on ``. You can +cherry-pick the commit from `` to `` by typing: + +.. code:: console + + $ git checkout myBranch-2 + $ git cherry-pick SHA1 + +If there are no conflicts, the displayed message should contain the commit +message and author information. In order to have the commit listed online, +conclude the cherry-pick by pushing the commit to the remote repository: + +.. code:: console + + $ git push myBranch-2 + diff --git a/docs/source/troubleshooting/cobratutorials.rst b/docs/source/troubleshooting/cobratutorials.rst new file mode 100644 index 0000000..5228e45 --- /dev/null +++ b/docs/source/troubleshooting/cobratutorials.rst @@ -0,0 +1,78 @@ +COBRA.tutorials +^^^^^^^^^^^^^^^ + +.. |warning| raw:: html + + warning + +|warning| This section is tailored to users who feel comfortable using +the terminal (or shell). It is recommended for other users +to follow :ref:`these instructions `. + +|warning| A Github account is required and `git` must be installed. An SSH key +must be set as explained in :ref:`prerequisites`. + +Fork and checkout your branch +----------------------------- + +1. Fork the `COBRA.tutorials repository `__ on Github. + +2. Clone the forked repository to ``fork-COBRA.tutorials`` located in a directory of your choice: + + .. code-block:: console + + $ git clone git@github.com:/COBRA.tutorials.git fork-COBRA.tutorials.git + +3. Change to the directory ``fork-COBRA.tutorials``: + + .. code-block:: console + + $ cd fork-COBRA.tutorials.git/ + +4. Set the upstream to the ``opencobra/COBRA.tutorials`` repository: + + .. code-block:: console + + $ git remote add upstream git@github.com:opencobra/COBRA.tutorials.git + +5. Fetch from the upstream repository + + .. code-block:: console + + $ git fetch upstream + +6. Checkout a new branch from ``develop``: + + .. code-block:: console + + $ git checkout -b upstream/develop + +7. Now, make your changes in the tutorial in MATLAB. + + +Submit your changes and open a pull request +------------------------------------------- + +8. Once you are done making changes, add the files to your branch, where ``tutorial_`` is the name of the tutorial. Make sure to add the ``.m`` and the ``.mlx`` files. + + .. code-block:: console + + $ git add tutorial_.m + $ git add tutorial_.mlx + $ git commit -m "Changes to tutorial_" + +9. Push your commits on ```` to your fork: + + .. code-block:: console + + $ git push origin + +10. Browse to your fork on ``https://www.github.com//COBRA.tutorials``, where ```` is your Github username. + +11. Click on ``Compare & Pull Request``. + +12. Change the target branch ``develop``. + +13. Submit your pull request. + +14. Wait until your pull request is accepted. diff --git a/runtests.sh b/runtests.sh deleted file mode 100644 index 5f2dff0..0000000 --- a/runtests.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -cd ./test -/mnt/data/MATLAB/$MATLAB_VER/bin/./matlab -nodesktop -nosplash -r "launchTests;" < inputCI.txt; -CODE=$? -exit $CODE diff --git a/src/addKeyToKnownHosts.m b/src/addKeyToKnownHosts.m new file mode 100644 index 0000000..79f0862 --- /dev/null +++ b/src/addKeyToKnownHosts.m @@ -0,0 +1,65 @@ +function keyAdded = addKeyToKnownHosts(callerName) +% Checks if the public key to `site.ext` exists +% If the public key of the `site.ext` does not exist, +% adds the public key to the known hosts +% +% USAGE: +% +% keyAdded = addKeyToKnownHosts(callerName) +% +% INPUT: +% callerName: Name of the function calling (default: empty string) +% +% OUTPUT: +% keyAdded: Boolean (true if key has been added successfully or exists) +% +% .. Author: +% - Laurent Heirendt + + global gitCmd + + % set default arguments + if ~exist('callerName', 'var') + callerName = ''; + end + + % add github.com as a known host + [status_keyscan, result_keyscan] = system('ssh-keyscan'); + + % user directory + if ispc + homeDir = getenv('userprofile'); + else + homeDir = getenv('HOME'); + end + + if status_keyscan == 1 && ~isempty(strfind(result_keyscan, 'usage:')) + + % try to create the directory + [status_createDir, ~, ~] = mkdir([homeDir filesep '.ssh']); + + % touch the file first + system(['touch ', homeDir, filesep, '.ssh', filesep, 'known_hosts']); + + % read the known hosts file + [~, result_grep] = system(['grep "^github.com " ', homeDir, filesep, '.ssh', filesep, 'known_hosts']); + + if strcmp(result_grep, '') + [status_kh, result_kh] = system(['ssh-keyscan github.com >> ', homeDir, filesep, '.ssh', filesep, 'known_hosts']); + + if status_kh == 0 && ~isempty(strfind(result_kh, '# github.com')) + printMsg(mfilename, [callerName, ' github.com has been added to the known hosts']); + keyAdded = true; + else + fprintf(result_kh); + error([gitCmd.lead, ' [', mfilename, ']', callerName, ' github.com could not be added to the known hosts file in ~/.ssh/known_hosts']); + end + else + printMsg(mfilename, [callerName, ' github.com is already a known host.']); + keyAdded = true; + end + else + fprintf(result_keyscan); + error([gitCmd.lead, ' [', mfilename, ']', callerName, ' ssh-keyscan is not installed.']); + end +end diff --git a/src/checkBranchExistence.m b/src/checkBranchExistence.m index f779b7e..fbb53f4 100644 --- a/src/checkBranchExistence.m +++ b/src/checkBranchExistence.m @@ -1,8 +1,18 @@ function branchExists = checkBranchExistence(branchName) -% devTools +% Checks if a branch exists locally % -% PURPOSE: checks if a branch exists locally +% USAGE: % +% branchExists = checkBranchExistence(branchName) +% +% INPUT: +% branchName: Name of the local branch to be checked for existence +% +% OUTPUT: +% branchExists: Boolean (true if `branchName` esists) +% +% .. Author: +% - Laurent Heirendt global gitConf diff --git a/src/checkDevTools.m b/src/checkDevTools.m index c7ac627..79c97e3 100644 --- a/src/checkDevTools.m +++ b/src/checkDevTools.m @@ -1,8 +1,12 @@ function checkDevTools() -% devTools +% Checks the configuration of the development tools % -% PURPOSE: checks the configuration of the development tools +% USAGE: % +% checkDevTools() +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd diff --git a/src/checkLocalFork.m b/src/checkLocalFork.m index caa2cbe..db636fe 100644 --- a/src/checkLocalFork.m +++ b/src/checkLocalFork.m @@ -1,8 +1,13 @@ function checkLocalFork() -% devTools +% Checks the configuration of remotes in the local copy of the fork % -% PURPOSE: checks the configuration of remotes in the local copy of the fork +% USAGE: % +% checkLocalFork() +% +% .. Author: +% - Laurent Heirendt + global gitConf global gitCmd diff --git a/src/checkRemoteBranchExistence.m b/src/checkRemoteBranchExistence.m new file mode 100644 index 0000000..08ad916 --- /dev/null +++ b/src/checkRemoteBranchExistence.m @@ -0,0 +1,36 @@ +function branchExists = checkRemoteBranchExistence(branchName) +% Checks if a branch exists locally +% +% USAGE: +% +% branchExists = checkRemoteBranchExistence(branchName) +% +% INPUT: +% branchName: Name of the remote branch to be checked for existence +% +% OUTPUT: +% branchExists: Boolean (true if `branchName` esists) +% +% .. Author: +% - Laurent Heirendt + + global gitConf + + % remove .git from the remoteRepoURL + if strcmpi(gitConf.remoteRepoURL(end-3:end), '.git') + tmpRepoName = gitConf.remoteRepoURL(1:end-4); + else + tmpRepoName = gitConf.remoteRepoURL; + end + + % retrieve a list of all the branches + [status_curl, result_curl] = system(['curl -s -k --head ' tmpRepoName '/tree/' branchName]); + + if status_curl == 0 && ~isempty(strfind(result_curl, '200 OK')) + printMsg(mfilename, ['The branch <' branchName '> exists remotely.']); + branchExists = true; + else + printMsg(mfilename, ['The remote <' branchName '> does not exist remotely.']); + branchExists = false; + end +end diff --git a/src/checkRemoteFork.m b/src/checkRemoteFork.m index 6f33c4a..3c395aa 100644 --- a/src/checkRemoteFork.m +++ b/src/checkRemoteFork.m @@ -1,8 +1,14 @@ function checkRemoteFork() -% devTools +% Checks whether the fork exists remotely % -% PURPOSE: checks whether the fork exists remotely +% USAGE: % +% checkRemoteFork() +% +% .. Author: +% - Laurent Heirendt + + global gitConf global gitCmd diff --git a/src/checkStatus.m b/src/checkStatus.m index 36592c0..6e728bc 100644 --- a/src/checkStatus.m +++ b/src/checkStatus.m @@ -1,8 +1,12 @@ function checkStatus() -% devTools +% Checks the status of the repository % -% PURPOSE: checks the status of the repository +% USAGE: % +% checkStatus() +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd diff --git a/src/checkSystem.m b/src/checkSystem.m index 85c576f..828fcc8 100644 --- a/src/checkSystem.m +++ b/src/checkSystem.m @@ -1,53 +1,82 @@ -function checkSystem(callerName) -% devTools +function checkSystem(callerName, repoName, printLevel) +% Checks the configuration of the system (installation of git and curl) % -% PURPOSE: checks the configuration of the system (installation of git and curl) +% USAGE: % +% checkSystem(callerName, repoName) +% +% INPUT: +% callerName: Name of the function calling `checkSystem()` +% repoName: Name of the repository for which the devTools shall +% be configured (default: `opencobra/cobratoolbox`) +% printLevel: Level of verbose +% +% .. Author: +% - Laurent Heirendt + global gitConf global gitCmd - % if a configuration has already been set, configure the devTools accordingly - if isempty(gitConf) - confDevTools(); - else - confDevTools(gitConf.launcher, gitConf.remoteRepoURL, gitConf.nickName, gitConf.verbose); - end - % set the callerName - if nargin < 1 + if ~exist('printLevel', 'var') callerName = ''; - verbose = true; else - verbose = false; callerName = ['(caller: ', callerName, ')']; end - if verbose - gitConfVerbose = gitConf.verbose; - gitConf.verbose = true; + % set the repoName if not given + if nargin < 2 || ~exist('repoName', 'var') + repoName = 'opencobra/cobratoolbox'; end - % check if git is properly installed - [status_gitVersion, result_gitVersion] = system('git --version'); + if ~exist('printLevel', 'var') && isempty(gitConf) + printLevel = 0; + end - if status_gitVersion == 0 && ~isempty(strfind(result_gitVersion, 'git version')) - printMsg(mfilename, [callerName, ' git is properly installed.']); + % if a configuration has already been set, configure the devTools accordingly + if isempty(gitConf) + % default configuration of the devTools is the DEFAULTREPONAME repository + confDevTools(repoName, 'printLevel', printLevel); else - fprintf(result_gitVersion); - error([gitCmd.lead, ' [', mfilename, ']', callerName, ' git is not installed. Please follow the guidelines how to install git.']); + % write instructions how to reset the devTools when they already configured + if strcmpi(callerName, 'contribute') + fprintf('\n'); + tmpPrintLevel = gitConf.printLevel; + gitConf.printLevel = 1; + printMsg(mfilename, [gitCmd.lead, ' The devTools are configured for the repository <', gitConf.nickName, '>']); + printMsg(mfilename, [gitCmd.lead, ' Please use >> resetDevTools() if you want to change the current configuration.']); + gitConf.printLevel = tmpPrintLevel; + + confDevTools(gitConf.nickName, 'remoteRepoURL', gitConf.remoteRepoURL, ... + 'launcher', gitConf.launcher, ... + 'printLevel', gitConf.printLevel); + end end - % check if curl is properly installed - [status_curl, result_curl] = system('curl --version'); + % only check whether git and curl are installed if the gitConf object is empty + if isempty(gitConf) + % add the public key from github.com to the known hosts + addKeyToKnownHosts(); + + % check if git is properly installed + [status_gitVersion, result_gitVersion] = system('git --version'); - if status_curl == 0 && ~isempty(strfind(result_curl, 'curl')) && ~isempty(strfind(result_curl, 'http')) - printMsg(mfilename, [callerName, ' curl is properly installed.']); - else - error([gitCmd.lead, ' [', mfilename, ']', callerName, ' curl is not installed. Please follow the guidelines how to install curl.']); - end + if status_gitVersion == 0 && ~isempty(strfind(result_gitVersion, 'git version')) + printMsg(mfilename, [callerName, ' git is properly installed.']); + else + fprintf(result_gitVersion); + error([gitCmd.lead, ' [', mfilename, ']', callerName, ' git is not installed. Please follow the guidelines how to install git.']); + end + + % check if curl is properly installed + [status_curl, result_curl] = system('curl --version'); - if verbose - gitConf.verbose = gitConfVerbose; + if status_curl == 0 && ~isempty(strfind(result_curl, 'curl')) && ~isempty(strfind(result_curl, 'http')) + printMsg(mfilename, [callerName, ' curl is properly installed.']); + else + fprintf(result_curl); + error([gitCmd.lead, ' [', mfilename, ']', callerName, ' curl is not installed. Please follow the guidelines how to install curl.']); + end end end diff --git a/src/checkoutBranch.m b/src/checkoutBranch.m index 39b3de6..18cab37 100644 --- a/src/checkoutBranch.m +++ b/src/checkoutBranch.m @@ -1,14 +1,22 @@ -function checkoutBranch(branchName, update_fork) -% devTools +function checkoutBranch(branchName, updateForkFlag) +% checks out a branch named locally and remotely % -% PURPOSE: checks out a branch named locally and remotely +% USAGE: % +% checkoutBranch(branchName, updateForkFlag) +% +% INPUT: +% branchName: Name of the local branch to be checked out +% updateForkFlag: Boolean to update the fork before checking out the branch +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd if nargin < 2 - update_fork = true; + updateForkFlag = true; end % save the currentDir @@ -31,50 +39,57 @@ function checkoutBranch(branchName, update_fork) % retrieve the status [status_gitStatus, result_gitStatus] = system('git status -s'); - if status_gitBranch == 0 && ~strcmpi('develop', currentBranch) && isempty(result_gitStatus) && status_gitStatus == 0 + % check if the develop branch exists remotely + if checkRemoteBranchExistence('develop') + mainBranch = 'develop'; + else + mainBranch = 'master'; % fall back to master, which always exists + end + + if status_gitBranch == 0 && ~strcmpi(mainBranch, currentBranch) && isempty(result_gitStatus) && status_gitStatus == 0 - printMsg(mfilename, ['The current feature (branch) ', currentBranch, ' is not the feature (branch).'], [gitCmd.fail, gitCmd.trail]); + printMsg(mfilename, ['The current feature (branch) ', currentBranch, ' is not the <' mainBranch '> feature (branch).'], [gitCmd.fail, gitCmd.trail]); % update the fork locally - if update_fork + if updateForkFlag updateFork(true); end % checkout the develop branch (after update of the fork) - [status_gitCheckout, result_gitCheckout] = system('git checkout develop'); + [status_gitCheckout, result_gitCheckout] = system(['git checkout ' mainBranch]); % retrieve the name of the current branch currentBranch = getCurrentBranchName(); - if status_gitCheckout == 0 && strcmpi('develop', currentBranch) - printMsg(mfilename, 'The current feature (branch) is .'); + if status_gitCheckout == 0 && strcmpi(mainBranch, currentBranch) + printMsg(mfilename, ['The current feature (branch) is <' mainBranch '>.']); else fprintf(result_gitCheckout); - error([gitCmd.lead, 'An error occurred and the feature (branch) cannot be checked out']); + error([gitCmd.lead, 'An error occurred and the <' mainBranch '> feature (branch) cannot be checked out']); end % reset the develop branch - [status_gitReset, result_gitReset] = system('git reset --hard upstream/develop'); + [status_gitReset, result_gitReset] = system(['git reset --hard upstream/' mainBranch]); if status_gitReset == 0 - if gitConf.verbose - fprintf([gitCmd.lead, ' [', mfilename, '] The current feature (branch) is .', gitCmd.success, gitCmd.trail]); + if gitConf.printLevel > 0 + fprintf([gitCmd.lead, ' [', mfilename, '] The current feature (branch) is <' mainBranch '>.', gitCmd.success, gitCmd.trail]); end else fprintf(result_gitReset); - error([gitCmd.lead, 'The feature (branch) cannot be checked out']); + error([gitCmd.lead, 'The <' mainBranch '> feature (branch) cannot be checked out']); end % update all submodules updateSubmodules(); % make sure that the develop branch is up to date - [status_gitPull, result_gitPull] = system('git pull origin develop'); + [status_gitPull, result_gitPull] = system(['git pull origin ' mainBranch]); if status_gitPull == 0 - printMsg(mfilename, 'The changes on the feature (branch) of your fork have been pulled.'); + printMsg(mfilename, ['The changes on the <' mainBranch '> feature (branch) of your fork have been pulled.']); else fprintf(result_gitPull); - error([gitCmd.lead, 'The changes on the feature (branch) could not be pulled.', gitCmd.fail]); + error([gitCmd.lead, 'The changes on the <' mainBranch '> feature (branch) could not be pulled.', gitCmd.fail]); end end @@ -87,7 +102,7 @@ function checkoutBranch(branchName, update_fork) % retrieve the status [status_gitStatus, result_gitStatus] = system('git status -s'); - if (status_gitStatus == 0 && isempty(result_gitStatus)) || ~update_fork + if (status_gitStatus == 0 && isempty(result_gitStatus)) || ~updateForkFlag % properly checkout the branch [status_gitCheckout, result_gitCheckout] = system(['git checkout ', checkoutFlag, ' ', branchName]); @@ -102,11 +117,11 @@ function checkoutBranch(branchName, update_fork) if status_gitStatus == 0 && isempty(result_gitStatus) % perform a rebase - [status_gitRebase, result_gitRebase] = system('git rebase develop'); + [status_gitRebase, result_gitRebase] = system(['git rebase ' mainBranch]); % if the message after rebase does not contain up to data and not cannot rebase if status_gitRebase == 0 && isempty(strfind(result_gitRebase, 'up to date')) && isempty(strfind(result_gitRebase, 'Cannot rebase')) - printMsg(mfilename, ['The <', branchName, '> feature (branch) has been rebased with .']); + printMsg(mfilename, ['The <', branchName, '> feature (branch) has been rebased with <' mainBranch '>.']); % push by force the rebased branch [status_gitPush, result_gitPush] = system(['git push origin ', branchName, ' --force']); @@ -120,7 +135,7 @@ function checkoutBranch(branchName, update_fork) [status_gitRebaseAbort, ~] = system('git rebase --abort'); if status_gitRebaseAbort == 0 - printMsg(mfilename, ['The rebase process of <', branchName,'> with has been aborted.'], [gitCmd.fail, gitCmd.trail]); + printMsg(mfilename, ['The rebase process of <', branchName, '> with <' mainBranch '> has been aborted.'], [gitCmd.fail, gitCmd.trail]); end % if the message after rebase contains : cannot rebase @@ -129,13 +144,14 @@ function checkoutBranch(branchName, update_fork) reply = input([gitCmd.lead, ' -> Do you want to reset your feature (branch) <', branchName, '>. Y/N [N]: '], 's'); if ~isempty(reply) || strcmpi(reply, 'y') || strcmpi(reply, 'yes') - [status_curl, result_curl] = system(['curl -s -k --head ', gitConf.remoteServerName, gitConf.userName, '/', gitConf.remoteRepoName, '/tree/', branchName]); - if status_curl == 0 && ~isempty(strfind(result_curl, '200 OK')) + branchNameExistsRemotely = checkRemoteBranchExistence(branchName); + + if branchNameExistsRemotely % hard reset of an existing branch [status_gitReset, result_gitReset] = system(['git reset --hard origin/', branchName]); if status_gitReset == 0 - printMsg(mfilename, ['The <', branchName, '> feature (branch) has not been rebased with and is up to date.']); + printMsg(mfilename, ['The <', branchName, '> feature (branch) has not been rebased with <' mainBranch '> and is up to date.']); else fprintf(result_gitReset); error([gitCmd.lead, ' [', mfilename, '] The <', branchName, '> could not be reset.', gitCmd.fail]); @@ -161,45 +177,45 @@ function checkoutBranch(branchName, update_fork) end end else - if gitConf.verbose + if gitConf.printLevel > 0 fprintf(result_gitCheckout); fprintf([gitCmd.lead, ' [', mfilename, '] The feature (branch) <', branchName, '> could not be checked out.', gitCmd.fail, gitCmd.trail]); end end else - if gitConf.verbose && ~strcmp(branchName, currentBranch) + if gitConf.printLevel > 0 && ~strcmp(branchName, currentBranch) fprintf(result_gitStatus); fprintf([gitCmd.lead, ' [', mfilename, '] Uncommited changes of the current feature (branch) <', currentBranch, '> have been migrated to the new feature <', branchName, '>.', gitCmd.success, gitCmd.trail]); end if ~strcmp(branchName, currentBranch) % checkout the develop branch (soft checkout without merg) - [status_gitCheckout, result_gitCheckout] = system('git checkout develop'); + [status_gitCheckout, result_gitCheckout] = system(['git checkout ' mainBranch]); % retrieve the name of the current branch currentBranch = getCurrentBranchName(); - if status_gitCheckout == 0 && strcmpi('develop', currentBranch) - printMsg(mfilename, 'The current feature (branch) is .'); + if status_gitCheckout == 0 && strcmpi(mainBranch, currentBranch) + printMsg(mfilename, ['The current feature (branch) is <' mainBranch '>.']); % update all submodules updateSubmodules(); % make sure that the develop branch is up to date - [status_gitPull, result_gitPull] = system('git pull origin develop'); + [status_gitPull, result_gitPull] = system(['git pull origin ' mainBranch]); if status_gitPull == 0 - printMsg(mfilename, 'The changes on the feature (branch) of your fork have been pulled.'); + printMsg(mfilename, ['The changes on the <' mainBranch '> feature (branch) of your fork have been pulled.']); else fprintf(result_gitPull); - error([gitCmd.lead, 'The changes on the feature (branch) could not be pulled.', gitCmd.fail]); + error([gitCmd.lead, 'The changes on the <' mainBranch '> feature (branch) could not be pulled.', gitCmd.fail]); end % checkout the branch but do not update the fork checkoutBranch(branchName, false); else fprintf(result_gitCheckout); - fprintf([gitCmd.lead, 'The feature (branch) cannot be checked out']); + fprintf([gitCmd.lead 'The <' mainBranch '> feature (branch) cannot be checked out']); end end end @@ -207,11 +223,12 @@ function checkoutBranch(branchName, update_fork) % check the system checkSystem(mfilename); - % if a branch does not exist remotely but exists locally, push it after confirmation from the user - [status_curl, result_curl] = system(['curl -s -k --head ', gitConf.remoteServerName, gitConf.userName, '/', gitConf.remoteRepoName, '/tree/', branchName]); + % check of the branch exists locally and remotely + branchExistsLocally = checkBranchExistence(branchName); + branchExistsRemotely = checkRemoteBranchExistence(branchName); % check if the branch exists remotely - if status_curl == 0 && ~isempty(strfind(result_curl, '200 OK')) && checkBranchExistence(branchName) + if branchExistsRemotely && branchExistsLocally printMsg(mfilename, ['The <', branchName, '> feature (branch) exists locally and remotely on <', gitConf.forkURL, '>.']); else % the branch exists locally but not remotely! diff --git a/src/cloneFork.m b/src/cloneFork.m index 4f5cda0..4897e35 100644 --- a/src/cloneFork.m +++ b/src/cloneFork.m @@ -1,8 +1,16 @@ function freshClone = cloneFork() -% devTools +% Clone the fork and update the submodules of the repository % -% PURPOSE: clones the fork and updates the submodules of the repository +% USAGE: % +% freshClone = cloneFork() +% +% OUTPUT: +% freshClone: Boolean (`true` if a new clone has been made) +% +% .. Author: +% - Laurent Heirendt + global gitConf global gitCmd diff --git a/src/confDevTools.m b/src/confDevTools.m new file mode 100644 index 0000000..dd7811f --- /dev/null +++ b/src/confDevTools.m @@ -0,0 +1,107 @@ +function confDevTools(repoName, varargin) +% Configure the devTools by defining the `gitConf` object +% +% USAGE: +% +% confDevTools(repoName, remoteRepoURL, varargin) +% +% INPUTS: +% repoName: Name of the repository (default: `'cobratoolbox'`) +% +% OPTIONAL INPUTS: +% remoteRepoURL: URL of the repository +% launcher: String with a header to be displayed when starting +% nickName: Short name of the repository +% printLevel: Verbose level (default: 1) +% +% Note: +% Currently, only 2 projects are defined: +% `The COBRA Toolbox `__ +% and `COBRA.tutorials `__ +% +% .. Author: +% - Laurent Heirendt, January 2018 +% + + global gitConf + global gitCmd + + % define default values + defaultPrintLevel = 0; + + % setup the parser + parser = inputParser(); + parser.addRequired('repoName', @ischar); + parser.addParamValue('remoteRepoURL', ['https://github.com/' repoName '.git'], @ischar); + + % set the defaultLauncher + if strcmpi(repoName, 'opencobra/cobratoolbox') + c = clock; + defaultLauncher = ['\n\n _____ _____ _____ _____ _____ |\n / ___| / _ \\ | _ \\ | _ \\ / ___ \\ | COnstraint-Based Reconstruction and Analysis\n | | | | | | | |_| | | |_| | | |___| | | The COBRA Toolbox - ', num2str(c(1)) , '\n | | | | | | | _ { | _ / | ___ | |\n | |___ | |_| | | |_| | | | \\ \\ | | | | | Documentation:\n \\_____| \\_____/ |_____/ |_| \\_\\ |_| |_| | http://opencobra.github.io/cobratoolbox\n | \n\n']; + defaultNickName = 'cobratoolbox'; + elseif strcmpi(repoName, 'opencobra/COBRA.tutorials') + defaultLauncher = '\n\n ~~~ COBRA.tutorials ~~~\n\n'; + defaultNickName = 'COBRA.tutorials'; + else + defaultLauncher = ['\n\n ~~~ ' repoName ' ~~~\n\n']; + defaultNickName = repoName; + end + parser.addParamValue('launcher', defaultLauncher, @ischar); + parser.addParamValue('nickName', defaultNickName, @ischar); + parser.addParamValue('printLevel', defaultPrintLevel, @(x) isnumeric(x)); + + % parse the input arguments + if ~isempty(varargin) + parser.parse(repoName, varargin{:}); + else + parser.parse(repoName); + end + + % retrieve the variables + repoName = parser.Results.repoName; + remoteRepoURL = parser.Results.remoteRepoURL; + printLevel = parser.Results.printLevel; + + % strip the .git at the end + tmpRemoteRepoURL = remoteRepoURL(1:end-4); + + % check if the remoteRepoURL exists before proceeding + [status_curl, result_curl] = system(['curl -s -k --head ', tmpRemoteRepoURL]); + if ~(status_curl == 0 && ~isempty(strfind(result_curl, '200 OK'))) + error([' [', mfilename, '] The URL (' remoteRepoURL ') is not reachable or does not exist.']); + end + + % set the default nickName + urlSplit = strsplit(remoteRepoURL, '/'); + tmpNickName = strsplit(urlSplit{end}, '.git'); + nickName = tmpNickName{1}; + + % define the configuration of other projects here + if printLevel > 0 + fprintf([' -- Assuming the default configuration (', nickName, ' repository)\n']); + end + + % definition of parameters + gitConf.leadForkDirName = 'fork-'; + gitConf.exampleBranch = 'add-constraints'; + + % define the printLevel + gitConf.printLevel = printLevel; + gitConf.launcher = parser.Results.launcher; + gitConf.remoteRepoURL = remoteRepoURL; + gitConf.nickName = nickName; + + % define the URL of the devTools + gitConf.devToolsURL_SSH = 'git@github.com:opencobra/MATLAB.devTools.git'; + gitConf.devToolsURL_HTTPS = 'https://github.com/opencobra/MATLAB.devTools.git'; + gitConf.devTools_name = 'MATLAB.devTools'; + + % definition of commands + gitCmd.lead = 'dev> '; + gitCmd.success = ' (Success) '; + gitCmd.fail = ' (Error) '; + gitCmd.trail = '\n'; + + % print out a success message + printMsg(mfilename, [' The devTools have been configured (', nickName, ').']); +end diff --git a/src/configureFork.m b/src/configureFork.m index 3eae67b..2071f95 100644 --- a/src/configureFork.m +++ b/src/configureFork.m @@ -1,8 +1,12 @@ function configureFork() -% devTools +% Configures the remotes of the local fork (upstream) % -% PURPOSE: configures the remotes of the local fork (upstream) +% USAGE: % +% configureFork() +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd diff --git a/src/deleteContribution.m b/src/deleteContribution.m index bd18996..f60c390 100644 --- a/src/deleteContribution.m +++ b/src/deleteContribution.m @@ -1,8 +1,15 @@ function deleteContribution(branchName) -% devTools +% Delete an existing feature (branch) named `branchName` % -% PURPOSE: deletes and existing feature (branch) named +% USAGE: % +% deleteContribution(branchName) +% +% INPUT: +% branchName: Name of the local branch to be deleted +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd @@ -10,67 +17,76 @@ function deleteContribution(branchName) % change the directory to the local directory of the fork cd(gitConf.fullForkDir); - if gitConf.verbose + if gitConf.printLevel > 0 originCall = [' [', mfilename, '] ']; else originCall = ''; end if isempty(strfind(branchName, 'develop')) && isempty(strfind(branchName, 'master')) - reply = input([gitCmd.lead, originCall, 'Are you sure that you want to delete the feature (branch) <', branchName, '>? YES/NO [NO]: '], 's'); + reply = ''; - if ~isempty(reply) && strcmpi(reply, 'yes') % users MUST enter 'yes', not only 'y' + while isempty(reply) || ~strcmpi(reply, 'yes') - % checkout the develop branch - checkoutBranch('develop'); + reply = input([gitCmd.lead, originCall, 'Are you sure that you want to delete the feature (branch) <', branchName, '>? YES/NO [NO]: '], 's'); - % retrieve a list of all the branches - if ispc - filterColor = ''; - else - filterColor = '| tr -s "[:cntrl:]" "\n"'; - end + if strcmpi(reply, 'yes') % users MUST enter 'yes', not only 'y' + + % check if the develop branch exists remotely + if checkRemoteBranchExistence('develop') + mainBranch = 'develop'; + else + mainBranch = 'master'; % fall back to master, which always exists + end + + % checkout the develop branch + checkoutBranch(mainBranch); - [status_gitBranch, resultList] = system(['git branch --list ', filterColor]); + % retrieve a list of all the branches + if ispc + filterColor = ''; + else + filterColor = '| tr -s "[:cntrl:]" "\n"'; + end - % delete the local branch - if status_gitBranch == 0 - arrResult = strsplit(resultList, '\n'); - arrResult(~cellfun(@isempty, arrResult)); + [status_gitBranch, resultList] = system(['git branch --list ', filterColor]); - if checkBranchExistence(branchName) - % delete the branch locally - [status_gitBranchDelete, result_gitBranchDelete] = system(['git branch -D ', branchName]); + % delete the local branch + if status_gitBranch == 0 + arrResult = strsplit(resultList, '\n'); + arrResult(~cellfun(@isempty, arrResult)); - if status_gitBranchDelete == 0 - fprintf([gitCmd.lead, originCall, 'The local <', branchName, '> feature (branch) has been deleted.', gitCmd.success, gitCmd.trail]); + if checkBranchExistence(branchName) + % delete the branch locally + [status_gitBranchDelete, result_gitBranchDelete] = system(['git branch -D ', branchName]); + + if status_gitBranchDelete == 0 + fprintf([gitCmd.lead, originCall, 'The local <', branchName, '> feature (branch) has been deleted.', gitCmd.success, gitCmd.trail]); + else + fprintf(result_gitBranchDelete); + error([gitCmd.lead, ' [', mfilename,'] The local <', branchName,'> feature (branch) could not be deleted. You might have unpublished/uncommitted changes.', gitCmd.fail]); + end else - fprintf(result_gitBranchDelete); - error([gitCmd.lead, ' [', mfilename,'] The local <', branchName,'> feature (branch) could not be deleted. You might have unpublished/uncommitted changes.', gitCmd.fail]); + fprintf([gitCmd.lead, originCall, 'The local <', branchName,'> feature (branch) does not exist.', gitCmd.fail, gitCmd.trail]); end else - fprintf([gitCmd.lead, originCall, 'The local <', branchName,'> feature (branch) does not exist.', gitCmd.fail, gitCmd.trail]); + error([gitCmd.lead, ' [', mfilename,'] The list of features (branches) could not be retrieved.', gitCmd.fail]); end - else - error([gitCmd.lead, ' [', mfilename,'] The list of features (branches) could not be retrieved.', gitCmd.fail]); - end - % check if branch exists remotely - [status_curl, result_curl] = system(['curl -s -k --head ', gitConf.remoteServerName, gitConf.userName, '/', gitConf.remoteRepoName, '/tree/', branchName]); + % delete the remote branch + if checkRemoteBranchExistence(branchName) - % delete the remote branch - if status_curl == 0 && ~isempty(strfind(result_curl, '200 OK')) + [status_gitPush, result_gitPush] = system(['git push origin --delete ', branchName]); - [status_gitPush, result_gitPush] = system(['git push origin --delete ', branchName]); - - if status_gitPush == 0 - fprintf([gitCmd.lead, originCall, 'The remote <', branchName, '> feature (branch) has been deleted.', gitCmd.success, gitCmd.trail]); + if status_gitPush == 0 + fprintf([gitCmd.lead, originCall, 'The remote <', branchName, '> feature (branch) has been deleted.', gitCmd.success, gitCmd.trail]); + else + fprintf(result_gitPush); + error([gitCmd.lead, ' [', mfilename,'] The remote <', branchName,'> feature (branch) could not be deleted.', gitCmd.fail]); + end else - fprintf(result_gitPush); - error([gitCmd.lead, ' [', mfilename,'] The remote <', branchName,'> feature (branch) could not be deleted.', gitCmd.fail]); + fprintf([gitCmd.lead, originCall, 'The remote <', branchName,'> feature (branch) does not exist.', gitCmd.fail, gitCmd.trail]); end - else - fprintf([gitCmd.lead, originCall, 'The remote <', branchName,'> feature (branch) does not exist.', gitCmd.fail, gitCmd.trail]); end end else diff --git a/src/getCurrentBranchName.m b/src/getCurrentBranchName.m index a0f5bf0..39023ec 100644 --- a/src/getCurrentBranchName.m +++ b/src/getCurrentBranchName.m @@ -1,8 +1,17 @@ function currentBranch = getCurrentBranchName() -% devTools +% Retrieve the name of the current branch % -% PURPOSE: retrieve the name of the current branch +% USAGE: % +% currentBranch = getCurrentBranchName() +% +% OUTPUT: +% currentBranch: Name of the current branch +% +% .. Author: +% - Laurent Heirendt + + global gitConf global gitCmd diff --git a/src/history.m b/src/history.m index 4cbc936..e64e723 100644 --- a/src/history.m +++ b/src/history.m @@ -1,8 +1,17 @@ function history(fileName) -% devTools +% Displays the history of a file % -% PURPOSE: displays the history of a file +% USAGE: % +% history(fileName) +% +% INPUT: +% fileName: Name of the file for which the history shall be displayed +% +% .. Author: +% - Laurent Heirendt + + global gitConf fullPath = which(fileName); diff --git a/src/initContribution.m b/src/initContribution.m index f54a276..3c009a7 100644 --- a/src/initContribution.m +++ b/src/initContribution.m @@ -1,8 +1,15 @@ function initContribution(branchName) -% devTools +% Initializes a new feature (branch) named `branchName` % -% PURPOSE: initializes a new feature (branch) named +% USAGE: % +% initContribution(branchName) +% +% INPUT: +% branchName: Name of the local branch to be initialized +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd @@ -10,7 +17,7 @@ function initContribution(branchName) % initialize the development tools initDevTools(); - if gitConf.verbose + if gitConf.printLevel > 0 originCall = [' [', mfilename, '] ']; else originCall = ''; @@ -27,8 +34,10 @@ function initContribution(branchName) if ~isempty(strfind(branchName, 'develop')) || ~isempty(strfind(branchName, 'master')) branchName = ''; fprintf([gitCmd.lead, ' -> Please use a different name that does not contain or .', gitCmd.fail, gitCmd.trail]); - else + elseif ~isempty(branchName) checkoutFlag = true; + else + branchName = ''; end end end diff --git a/src/initDevTools.m b/src/initDevTools.m index 8fc14d0..03f8a22 100644 --- a/src/initDevTools.m +++ b/src/initDevTools.m @@ -1,14 +1,32 @@ -function initDevTools() -% devTools +function initDevTools(repoName) +% Initializes the development tools (username and email are requested if not configured) % -% PURPOSE: initializes the development tools (username and email are requested if not configured) +% USAGE: % +% initDevTools(repoName) +% +% INPUT: +% repoName: Name of the repository for which the devTools shall +% be configured (default: `opencobra/cobratoolbox`) +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd + global resetDevToolsFlag + global DEFAULTREPONAME + + % set the repoName if not given + if ~exist('repoName', 'var') + repoName = DEFAULTREPONAME; + end + + resetDevToolsFlag = true; + + finishup = onCleanup(@() resetDevTools()); % check the system and set the configuration - checkSystem(mfilename); + checkSystem(mfilename, repoName); if ~isfield(gitConf, 'userName'), gitConf.userName = []; end if ~isfield(gitConf, 'localDir'), gitConf.localDir = []; end @@ -19,10 +37,14 @@ function initDevTools() gitConf.remoteRepoName = gitConf.remoteRepoURL(sepIndices(4)+1:end-4); gitConf.remoteUserName = gitConf.remoteRepoURL(sepIndices(3)+1:sepIndices(4)-1); + % ignore case for the current fork (avoids problems for untracked files with case conflicts) + [status_gitIgnoreCase, result_gitIgnoreCase] = system('git config core.ignorecase true'); + + % retrieve the user name [status_gitConfUserGet, result_gitConfUserGet] = system('git config --get user.github-username'); gitConf.userName = strtrim(result_gitConfUserGet); - if gitConf.verbose + if gitConf.printLevel > 0 originCall = [' [', mfilename, '] ']; else originCall = ''; @@ -69,17 +91,26 @@ function initDevTools() end end + % define the name of the local fork directory + gitConf.forkDirName = strrep([gitConf.leadForkDirName, gitConf.remoteRepoName], '\', '\\'); + + % retrieve the directory of the fork from the local git configuration + [~, result_gitConfForkDirGet] = system(['git config --get user.', gitConf.leadForkDirName, gitConf.nickName, '.path']); + gitConf.fullForkDir = strtrim(result_gitConfForkDirGet); + gitConf.localDir = gitConf.fullForkDir; + % check if the fork exists remotely checkRemoteFork(); - % request the local directory - if isempty(gitConf.localDir) + % request the local directory if the fullForkDir is not yet known + if isempty(gitConf.localDir) && isempty(gitConf.fullForkDir) createDir = false; while ~createDir - reply = input([gitCmd.lead, originCall, ' -> Please define the local path to your fork\n current: ', strrep(pwd,'\','\\'),'\n Enter the path (press ENTER to use the current path): '], 's'); + reply = input([gitCmd.lead, originCall, ' -> Please define the location of your fork\n current: ', strrep(pwd,'\','\\'),'\n Enter the path (press ENTER to use the current path): '], 's'); + % define the local directory as the current directory if the reply is empty if isempty(reply) gitConf.localDir = strrep(pwd, '\', '\\'); else @@ -91,21 +122,30 @@ function initDevTools() gitConf.localDir = strrep([gitConf.localDir, filesep], '\', '\\'); end - % warn the user of not using a fork-cobratoolbox or cobratoolbox directory as it will be cloned - if ~isempty(strfind(gitConf.localDir, gitConf.nickName)) || exist([gitConf.localDir, '/.git'], 'dir') == 7 % contains the nickname or a .git folder - reply = input([gitCmd.trail, gitCmd.lead, originCall, ' -> The specified directory already contains a ', gitConf.nickName, ' copy (clone) or is a git directory.', ... - gitCmd.trail, gitCmd.lead, originCall, ' -> Please provide the directory into which your fork should be cloned. Do you want to continue? Y/N [Y]:'], 's'); - - if isempty(reply) || strcmpi(reply, 'y') || strcmpi(reply, 'yes') - createDir = true; - else - createDir = false; + % strip the fork-nickName folder from the localDir if present + if ~isempty(gitConf.localDir) && length(gitConf.forkDirName) <= length(gitConf.localDir) + if strcmp(gitConf.localDir(end-length(gitConf.forkDirName)+1:end), gitConf.forkDirName) + gitConf.localDir = gitConf.localDir(1:end-length(gitConf.forkDirName)); end + end + + % warn the user of not using a fork-nickName directory or a git cloned directory as it will be cloned + if ~isempty(strfind(gitConf.localDir, gitConf.nickName)) % contains the nickname + printMsg(mfilename, ['The specified directory already contains a ', gitConf.nickName, ' copy (clone).'], gitCmd.trail); + createDir = true; + gitConf.localDir = gitConf.localDir(1:end-length(gitConf.nickName)-1-length(gitConf.leadForkDirName)); + + elseif exist([gitConf.localDir, '/.git'], 'dir') == 7 % contains a .git folder + printMsg(mfilename, ['The specified directory already is a git repository (git-tracked).'], gitCmd.trail); + else createDir = true; end end + % define the fork directory name + gitConf.fullForkDir = strrep([gitConf.localDir, gitConf.forkDirName], '\', '\\'); + if exist(gitConf.localDir, 'dir') ~= 7 reply = input([gitCmd.lead, originCall, ' -> The specified directory (', gitConf.localDir, ') does not exist. Do you want to create it? Y/N [Y]:'], 's'); @@ -119,9 +159,16 @@ function initDevTools() end end - % define the fork directory name - gitConf.forkDirName = strrep([gitConf.leadForkDirName, gitConf.remoteRepoName], '\', '\\'); - gitConf.fullForkDir = strrep([gitConf.localDir, gitConf.forkDirName], '\', '\\'); + resetDevToolsFlag = false; + + % permanently store the fork directory in the git configuration (ask the user explicitly) + [status_gitConfForkDirSet, result_gitConfForkDirSet] = system(['git config --global user.', gitConf.leadForkDirName, gitConf.nickName, '.path "', gitConf.fullForkDir, '"']); + if status_gitConfForkDirSet == 0 + fprintf([gitCmd.lead, originCall, 'Your fork directory has been set to: ', gitConf.fullForkDir, '. ', gitCmd.success, gitCmd.trail]); + else + fprintf(result_gitConfForkDirSet); + error([gitCmd.lead, ' [', mfilename,'] Your fork directory could not be set.', gitCmd.fail]); + end % clone the fork freshClone = cloneFork(); @@ -149,7 +196,9 @@ function initDevTools() % print the current configuration fprintf([gitCmd.lead, originCall, ' -- Configuration -------- ', gitCmd.trail]) fprintf([gitCmd.lead, originCall, ' GitHub username: ', gitConf.userName, gitCmd.trail]); + fprintf([gitCmd.lead, originCall, ' GitHub email: ', gitConf.userEmail, gitCmd.trail]); fprintf([gitCmd.lead, originCall, ' Local directory : ', gitConf.fullForkDir, gitCmd.trail]) fprintf([gitCmd.lead, originCall, ' Remote fork URL: ', gitConf.forkURL, gitCmd.trail]); fprintf([gitCmd.lead, originCall, ' Remote repository URL: ', gitConf.remoteRepoURL, gitCmd.trail]); + end diff --git a/src/listFeatures.m b/src/listFeatures.m index 64b1a85..dca884f 100644 --- a/src/listFeatures.m +++ b/src/listFeatures.m @@ -1,8 +1,20 @@ function [exitFlag, currentBranch, arrResult, exampleBranch] = listFeatures() -% devTools +% Lists all available branches/features % -% PURPOSE: lists all available branches/features +% USAGE: % +% [exitFlag, currentBranch, arrResult, exampleBranch] = listFeatures() +% +% OUTPUT: +% exitFlag: Boolean (true if proper exit of function) +% currentBranch: Name of current branch +% arrResult: Cell with all names of branches +% exampleBranch: Name of a branch given as an example +% +% .. Author: +% - Laurent Heirendt + + global gitConf @@ -24,12 +36,19 @@ % give an example name exampleBranch = gitConf.exampleBranch; + % check if the develop branch exists remotely + if checkRemoteBranchExistence('develop') + nbBranches = 3; + else + nbBranches = 2; + end + if status == 0 arrResult = regexp(result,'\s+','split'); %strsplit is not compatible with older versions of MATLAB arrResult = strtrim(arrResult); arrResult = arrResult(~cellfun(@isempty, arrResult)); - if length(arrResult) > 2 + if length(arrResult) > nbBranches fprintf('\n Available features are:\n'); % list the number of available features @@ -46,15 +65,22 @@ fprintf('\n'); else - reply = input(' -> You do not have any features (branches). Do you want to start a new feature (branch)? Y/N [Y]: ', 's'); - - % decide whether to start a new feature (branch) or not - if ~isempty(reply) && (strcmpi(reply, 'y') || strcmpi(reply, 'yes')) - initContribution; - exitFlag = true; - else - fprintf(' -> Please start again. Goodbye.\n') - exitFlag = true; + reply = ''; + while isempty(reply) + + reply = input(' -> You do not have any features (branches). Do you want to start a new feature (branch)? Y/N [Y]: ', 's'); + + % decide whether to start a new feature (branch) or not + if strcmpi(reply, 'y') || strcmpi(reply, 'yes') + initContribution; + exitFlag = true; + break; + elseif strcmpi(reply, 'n') || strcmpi(reply, 'no') + fprintf(' -> Please start again. Goodbye.\n') + exitFlag = true; + else + reply = ''; + end end end end diff --git a/src/openPR.m b/src/openPR.m index d71381b..cb6111a 100644 --- a/src/openPR.m +++ b/src/openPR.m @@ -1,8 +1,15 @@ function openPR(branchName) -% devTools +% Provides a pull request URL from to on the upstream % -% PURPOSE: provides a pull request URL from to on the upstream +% USAGE: % +% openPR(branchName) +% +% INPUT: +% branchName: Name of the branch for which a pull request (PR) shall be opened +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd @@ -10,14 +17,21 @@ function openPR(branchName) % change the directory to the local directory of the fork cd(gitConf.fullForkDir); - if gitConf.verbose + if gitConf.printLevel > 0 originCall = [' [', mfilename, '] ']; else originCall = ''; end + % check if the develop branch exists remotely + if checkRemoteBranchExistence('develop') + mainBranch = 'develop'; + else + mainBranch = 'master'; % fall back to master, which always exists + end + % define the URL of the pull request - prURL = [gitConf.remoteRepoURL(1:end-4), '/compare/develop...', gitConf.userName, ':', branchName]; + prURL = [gitConf.remoteRepoURL(1:end-4), '/compare/' mainBranch '...', gitConf.userName, ':', branchName]; % check if this URL exists [status_curl, result_curl] = system(['curl -s -k --head ', prURL]); diff --git a/src/printMsg.m b/src/printMsg.m index 8e790a1..fa02796 100644 --- a/src/printMsg.m +++ b/src/printMsg.m @@ -1,17 +1,31 @@ function printMsg(fileName, msg, endMsg) -% devTools +% Print a message % -% PURPOSE: print a message +% USAGE: % +% printMsg(fileName, msg, endMsg) +% +% INPUT: +% fileName: Name of the file from which the message is issued +% msg: Message as string +% endMsg: End of message, generally a new line character +% +% .. Author: global gitConf global gitCmd - if nargin < 3 - endMsg = [gitCmd.success, gitCmd.trail]; - end + % define the message + if ~isempty(gitConf) && ~isempty(gitCmd) + % define the end of the message + if nargin < 3 + endMsg = [gitCmd.success, gitCmd.trail]; + end - if gitConf.verbose - fprintf([gitCmd.lead, ' [', fileName, '] ', msg, endMsg]); + if gitConf.printLevel > 0 + fprintf([gitCmd.lead, ' [', fileName, '] ', msg, endMsg]); + end + else + fprintf([' [', fileName, '] ', msg]); end end diff --git a/src/resetDevTools.m b/src/resetDevTools.m index ced660f..d1cd136 100644 --- a/src/resetDevTools.m +++ b/src/resetDevTools.m @@ -1,27 +1,64 @@ -function resetDevTools() -% devTools +function resetDevTools(hardReset) +% Reset the configuration of the development tools % -% PURPOSE: reset the configuration of the development tools +% USAGE: % +% resetDevTools() +% +% INPUTS: +% hardReset: Boolean to hard reset the devTools +% (changes the local `git` configuration) (default: `false`) +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd + global resetDevToolsFlag + + if ~exist('hardReset', 'var') + hardReset = false; + end % call checkSystem to set default values for gitConf and gitCmd checkSystem(mfilename); - % unset the user name - [status_gitConfUserGet, result_gitConfUserGet] = system('git config --global --unset-all user.github-username'); + if resetDevToolsFlag + if hardReset + % unset the path to the local fork + [status_gitConfForkDirGet, result_gitConfForkDirGet] = system(['git config --global --unset user.', gitConf.leadForkDirName, gitConf.nickName, '.path']); - if status_gitConfUserGet == 0 - printMsg(mfilename, 'Your Github username has been removed.'); - else - fprintf(result_gitConfUserGet); - fprintf([gitCmd.lead, ' [', mfilename,'] Your Github username could not be removed.', gitCmd.fail, gitCmd.trail]); - end + if status_gitConfForkDirGet == 0 + printMsg(mfilename, 'Your fork directory has been removed from your local git configuration.'); + else + fprintf(result_gitConfForkDirGet); + fprintf([gitCmd.lead, ' [', mfilename,'] Your fork directory could not be removed from your local git configuration.', gitCmd.fail, gitCmd.trail]); + end - clear global gitConf; - clear global gitCmd; + % unset the user name + [status_gitConfUserGet, result_gitConfUserGet] = system('git config --global --unset-all user.github-username'); - fprintf([' [', mfilename, '] The development tools have been reset.\n']); + if status_gitConfUserGet == 0 + printMsg(mfilename, 'Your Github username has been removed from your local git configuration.'); + else + fprintf(result_gitConfUserGet); + fprintf([gitCmd.lead, ' [', mfilename,'] Your Github username could not be removed from your local git configuration.', gitCmd.fail, gitCmd.trail]); + end + end + + clear global gitConf; + clear global gitCmd; + clear global resetDevToolsFlag; + + % define an error message + if hardReset + resetMode = 'hard'; + else + resetMode = 'soft'; + end + + fprintf([' [', mfilename, '] The development tools have been reset (' resetMode ' reset).\n']); + else + resetDevToolsFlag = true; + end end diff --git a/src/resetLocalFork.m b/src/resetLocalFork.m index 13a5931..b28b41d 100644 --- a/src/resetLocalFork.m +++ b/src/resetLocalFork.m @@ -1,8 +1,13 @@ function resetLocalFork() -% devTools +% Clean all files in the working directory and reset the fork % -% PURPOSE: clean all files in the working directory and reset the fork +% USAGE: % +% resetLocalFork() +% +% .. Author: +% - Laurent Heirendt + global gitConf global gitCmd diff --git a/src/submitContribution.m b/src/submitContribution.m index 4a7612c..9267fd8 100644 --- a/src/submitContribution.m +++ b/src/submitContribution.m @@ -1,8 +1,15 @@ function submitContribution(branchName) -% devTools +% Submit an existing feature (branch) named `branchName` % -% PURPOSE: submit an existing feature (branch) named +% USAGE: % +% submitContribution(branchName) +% +% INPUT: +% branchName: Name of the local branch to be pushed to the git server +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd @@ -13,7 +20,7 @@ function submitContribution(branchName) % check if branch exists checkoutBranch(branchName); - if gitConf.verbose + if gitConf.printLevel > 0 originCall = [' [', mfilename, '] ']; else originCall = ''; @@ -150,14 +157,57 @@ function submitContribution(branchName) if countAddFiles > 0 fprintf([gitCmd.lead, originCall, 'You have selected ', num2str(countAddFiles), ' files to be added in one commit.', gitCmd.trail]); - commitMsg = input([gitCmd.lead, originCall, ' -> Please enter a commit message (example: "Fixing bug with input arguments"): '], 's'); + % define prohibited sequences + dictFlags = {'yy', 'nn', 'commit', 'abc'}; + + % initialize loop flag + incorrectCommitMsg = true; + + loopCounter = 0; + + % loop as long as the commit message is not correct + while incorrectCommitMsg && loopCounter < 10 + % ask the user for a commit message + commitMsg = input([gitCmd.lead, originCall, ' -> Please enter a commit message (example: "Fixing bug with input arguments"): '], 's'); - if ~isempty(commitMsg) + % omit non literal characters + commitMsg = regexprep(commitMsg, '[^a-zA-Z0-9_-?! ]', ''); - if ~strcmp(commitMsg(1), '"') || ~strcmp(commitMsg(end), '"') - commitMsg = ['"', commitMsg, '"']; + % trim the commitMsg + commitMsg = strtrim(commitMsg); + + % add double quotes to the commit message if not set + if isempty(commitMsg) + incorrectCommitMsg = true; + else + if ~strcmp(commitMsg(1), '"') || ~strcmp(commitMsg(end), '"') + commitMsg = ['"', commitMsg, '"']; + end end + % NOTE: anything below assumes "commitMsg" + + % if the commit message is not empty and minimum 5 characters (+2 quotes) + for k = 1:length(dictFlags) + if length(commitMsg) >= 4+2 && isempty(strfind(commitMsg, dictFlags{k})) + incorrectCommitMsg = false; + continue; + else + incorrectCommitMsg = true; + break; + end + end + + if incorrectCommitMsg + warning([gitCmd.lead, 'The commit message must be at least 5 characters long and not contain the word `commit`.']); + end + + % increment the loop counter + loopCounter = loopCounter + 1; + end + + % set the commit message + if ~incorrectCommitMsg [status_gitCommit, result_gitCommit] = system(['git commit -m', commitMsg]); fprintf([gitCmd.lead, originCall, 'Your commit message has been set.', gitCmd.success, gitCmd.trail]); if status_gitCommit == 0 @@ -167,7 +217,7 @@ function submitContribution(branchName) error([gitCmd.lead, ' [', mfilename,'] Your commit message cannot be set.', gitCmd.fail]); end else - error([gitCmd.lead, ' [', mfilename,'] Please enter a commit message that has more than 10 characters.', gitCmd.fail]); + error([gitCmd.lead, ' [', mfilename,'] Your commit message was not accepted.', gitCmd.fail]); end end diff --git a/src/updateDevTools.m b/src/updateDevTools.m index 15902ac..6a94d30 100644 --- a/src/updateDevTools.m +++ b/src/updateDevTools.m @@ -1,8 +1,12 @@ function updateDevTools() -% devTools +% Update the devTools and set the SSH origin if necessary % -% PURPOSE: update the devTools and set the SSH origin if necessary +% USAGE: % +% updateDevTools() +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd diff --git a/src/updateFork.m b/src/updateFork.m index ee8b31e..f66b36d 100644 --- a/src/updateFork.m +++ b/src/updateFork.m @@ -1,8 +1,15 @@ function updateFork(force) -% devTools +% Updates the fork and the submodules of the repository % -% PURPOSE: updates the fork and the submodules of the repository +% USAGE: % +% updateFork(force) +% +% INPUT: +% force: Boolean flag to use force for updating the fork +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd @@ -18,7 +25,11 @@ function updateFork(force) currentDir = strrep(pwd, '\', '\\'); % list the branches that should be updated - branches = {'master', 'develop'}; + if checkRemoteBranchExistence('develop') + branches = {'master', 'develop'}; + else + branches = {'master'}; % fall back to master, which always exists + end % change to the directory of the fork cd(gitConf.fullForkDir) @@ -46,7 +57,7 @@ function updateFork(force) if status_curl == 0 && ~isempty(strfind(result_curl, '200 OK')) % pull eventual changes from other contributors or administrators - [status_gitFetchOrigin, result_gitFetchOrigin] = system('git fetch origin '); % no pull + [status_gitFetchOrigin, result_gitFetchOrigin] = system('git fetch origin'); % no pull if status_gitFetchOrigin == 0 printMsg(mfilename, 'Changes of fork (origin) fetched.'); else @@ -78,6 +89,7 @@ function updateFork(force) fprintf(result_gitCheckout); printMsg(mfilename, ['The feature (branch) <', branches{k}, '> could not be checked out.']); end + else [status_gitCheckoutCreate, result_gitCheckoutCreate] = system(['git checkout -b ', branches{k}]); @@ -90,12 +102,23 @@ function updateFork(force) end % determine the number of commits that the local master branch is behind - [status_gitCount, result_gitCount] = system(['git rev-list --left-right --count ', branches{k}, '...upstream/', branches{k}]); + [status_gitCountUpstream, result_gitCountUpstream] = system(['git rev-list --left-right --count ', branches{k}, '...upstream/', branches{k}]); - if status_gitCount == 0 - commitsAheadBehind = str2num(char(strsplit(result_gitCount))); + [status_gitCountOrigin, result_gitCountOrigin] = system(['git rev-list --left-right --count ', branches{k}, '...origin/', branches{k}]); - if length(commitsAheadBehind) > 0 && commitsAheadBehind(2) > 0 + if status_gitCountUpstream == 0 && status_gitCountOrigin == 0 + commitsAheadBehindUpstream = str2num(char(strsplit(result_gitCountUpstream))); + commitsAheadBehindOrigin = str2num(char(strsplit(result_gitCountOrigin))); + + if (length(commitsAheadBehindUpstream) > 0 && commitsAheadBehindUpstream(2) > 0) || (length(commitsAheadBehindOrigin) > 0 && commitsAheadBehindOrigin(1) > 0) + + [status_gitPull, result_gitPull] = system(['git pull origin ', branches{k}]); + if status_gitPull == 0 + printMsg(mfilename, ['The <', branches{k}, '> feature (branch) of the fork could not be pulled.']); + else + fprintf(result_gitPull); + error([gitCmd.lead, ' [', mfilename,'] Impossible to pull changes from the <', branches{k}, '> feature (branch) of the fork.', gitCmd.fail]); + end if ~force % merge the changes from upstream to the branch @@ -141,11 +164,15 @@ function updateFork(force) end end end + + % initialize and update the submodules + updateSubmodules(); else fprintf(resultList); error([gitCmd.lead, ' [', mfilename,'] Impossible to retrieve the features (branches) of your local fork.', gitCmd.fail]); end else + fprintf(result_gitStatus); printMsg(mfilename, ['The local fork cannot be updated as you have uncommitted changes. Please submit/publish them first.']); end diff --git a/src/updateSubmodules.m b/src/updateSubmodules.m index c1ddddf..8ce009b 100644 --- a/src/updateSubmodules.m +++ b/src/updateSubmodules.m @@ -1,12 +1,21 @@ function updateSubmodules() -% devTools +% Clones the submodules and updates the repository % -% PURPOSE: clones the submodules and updates the repository +% USAGE: % +% updateSubmodules() +% +% .. Author: +% - Laurent Heirendt global gitConf global gitCmd + currentDir = strrep(pwd, '\', '\\'); + + % change to the directory of the fork + cd(gitConf.fullForkDir) + % temporary disable ssl verification [status_setSSLVerify, result_setSSLVerify] = system('git config --global http.sslVerify false'); @@ -17,8 +26,8 @@ function updateSubmodules() error([gitCmd.lead, ' [', mfilename,'] Your global git configuration could not be changed.', gitCmd.fail]); end - % Update/initialize submodules - [status_gitSubmodule, result_gitSubmodule] = system('git submodule update --init'); + % initialize submodules + [status_gitSubmodule, result_gitSubmodule] = system('git submodule init'); if status_gitSubmodule == 0 printMsg(mfilename, 'The submodules have been initialized.'); @@ -27,13 +36,43 @@ function updateSubmodules() error([gitCmd.lead, ' [', mfilename,'] The submodules could not be initialized.', gitCmd.fail]); end - % reset each submodule - [status_gitReset result_gitReset] = system('git submodule foreach --recursive git reset --hard'); - if status_gitReset == 0 - printMsg(mfilename, 'The submodules have been reset.'); + % retrieve the count for each submodule + [status_gitSubmoduleCount, result_gitSubmoduleCount] = system('git submodule foreach --recursive git rev-list --count origin/master...HEAD'); + + % split the array at line breaks + arrResult = regexp(result_gitSubmoduleCount,'\n+','split'); %strsplit is not compatible with older versions of MATLAB + arrResult = strtrim(arrResult); + + % filter out the empty ones + arrResult = arrResult(~cellfun(@isempty, arrResult)); + + % calculate the total number of changes + sumChanges = 0; + nSubmodules = length(arrResult)/2; + for k = 1:nSubmodules + sumChanges = sumChanges + str2num(arrResult{2*k}); + end + + % update submodules + [status_gitSubmodule, result_gitSubmodule] = system('git submodule update'); + + if status_gitSubmodule == 0 + printMsg(mfilename, 'The submodules have been initialized.'); else - fprintf(result_gitReset); - error([gitCmd.lead, ' [', mfilename,'] The submodules could not be reset.', gitCmd.fail]); + fprintf(result_gitSubmodule); + error([gitCmd.lead, ' [', mfilename,'] The submodules could not be initialized.', gitCmd.fail]); + end + + % update the submodules + if sumChanges > 0 + % reset each submodule + [status_gitReset result_gitReset] = system('git submodule foreach --recursive git reset --hard'); + if status_gitReset == 0 + printMsg(mfilename, 'The submodules have been reset.'); + else + fprintf(result_gitReset); + error([gitCmd.lead, ' [', mfilename,'] The submodules could not be reset.', gitCmd.fail]); + end end % restore global configuration by unsetting http.sslVerify @@ -45,4 +84,7 @@ function updateSubmodules() fprintf(result_setSSLVerify); error([gitCmd.lead, ' [', mfilename,'] Your global git configuration could not be restored.', gitCmd.fail]); end + + % change back to the original directory + cd(currentDir); end diff --git a/test/inputCI.txt b/test/inputCI.txt index 686e50c..33f354e 100644 --- a/test/inputCI.txt +++ b/test/inputCI.txt @@ -1,10 +1,9 @@ cobrabot -~/ +/home/sbg-jenkins/ y n testFile1 n y testFile2 -n -n +message-test diff --git a/test/launchTests.m b/test/launchTests.m index 0a3b884..d3e059a 100644 --- a/test/launchTests.m +++ b/test/launchTests.m @@ -1,7 +1,7 @@ if ~isempty(strfind(getenv('HOME'), 'jenkins')) % do not change the paths below - addpath(genpath('/var/lib/jenkins/MOcov')); - addpath(genpath('/var/lib/jenkins/jsonlab')); + addpath(genpath('/home/sbg-jenkins/MOcov')); + addpath(genpath('/home/sbg-jenkins/jsonlab')); % change the directory on the CI server cd([pwd, '/../']) @@ -69,11 +69,12 @@ end end - % remove the old badge - system('rm /var/lib/jenkins/userContent/codegrade-MATLABdevTools.svg'); - % set the new badge - system(['cp /var/lib/jenkins/userContent/codegrade-', grade, '.svg /var/lib/jenkins/userContent/codegrade-MATLABdevTools.svg']); + system(['cp /mnt/prince-data/jenkins/userContent/codegrade-', grade, '.svg /mnt/prince-data/jenkins/userContent/codegrade-MATLABdevTools.svg']); + + % secure copy the badge from the slave + system('scp -P 8022 /mnt/prince-data/jenkins/userContent/codegrade-MATLABdevTools.svg jenkins@prince-server.lcsb.uni.lux:/var/lib/jenkins/userContent'); + end try diff --git a/test/testCheckSystem.m b/test/testCheckSystem.m index 0ffec65..b31931e 100644 --- a/test/testCheckSystem.m +++ b/test/testCheckSystem.m @@ -5,13 +5,14 @@ launcher = '\n\n ~~~ MATLAB.devTools ~~~\n\n'; remoteRepoURL = 'https://github.com/uni-lu/MATLAB.devTools.CI.git'; nickName = 'MATLAB.devTools.CI'; -verbose = true; +printLevel = 1; % reset the development tools resetDevTools(); % set the configuration -confDevTools(launcher, remoteRepoURL, nickName, verbose); +confDevTools(nickName, 'remoteRepoURL', remoteRepoURL, 'launcher', launcher, ... + 'nickName', nickName, 'printLevel', printLevel); % check the system checkSystem();