From d94530fec174e04e12d2e656338ded4dbaf38b44 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 12 Jun 2019 18:21:25 -0600 Subject: [PATCH 01/41] Fix #16 --- docs/changelog.rst | 16 +++++++++++++++- docs/command-reference.rst | 12 ++++++------ src/degasolv/cli.clj | 6 +++--- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 25d6a80..4ca10a3 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -17,6 +17,19 @@ and this project adheres to `Semantic Versioning`_. Added +++++ +Changed ++++++++ + +Fixed ++++++ + + +`2.0.0`_ +-------- + +Added ++++++ + - Documentation saying what return codes are given and what they mean. - For #15, added ability to specify output format for ``display-config``. @@ -308,7 +321,8 @@ Added - This isn't the first release, but for the purposes of these docs, it is :D -.. _Unreleased: https://github.com/djhaskin987/degasolv/compare/1.12.1...HEAD +.. _Unreleased: https://github.com/djhaskin987/degasolv/compare/2.0.0...HEAD +.. _2.0.0: https://github.com/djhaskin987/degasolv/compare/1.12.1...2.0.0 .. _1.12.1: https://github.com/djhaskin987/degasolv/compare/1.12.0...1.12.1 .. _1.12.0: https://github.com/djhaskin987/degasolv/compare/1.11.0...1.12.0 .. _1.11.0: https://github.com/djhaskin987/degasolv/compare/1.10.0...1.11.0 diff --git a/docs/command-reference.rst b/docs/command-reference.rst index 7308520..cba2c1d 100644 --- a/docs/command-reference.rst +++ b/docs/command-reference.rst @@ -414,17 +414,17 @@ returns a page that looks something like this:: --conflict-strat STRAT exclusive May be 'exclusive', 'inclusive' or 'prioritized'. --repository INDEX Search INDEX for packages. ** --enable-alternatives Consider all alternatives (default) - --id true ID (name) of the package + --id ID ID (name) of the package --query QUERY Display packages matching query string. --disable-alternatives Consider only first alternatives --add-to INDEX Add to repo index INDEX --card-file FILE ./out.dscard The name of the card file --present-package PKG Hard present package. ** --resolve-strat STRAT thorough May be 'fast' or 'thorough'. - --location true URL or filepath of the package + --location LOCATION URL or filepath of the package --package-system SYS degasolv May be 'degasolv' or 'apt'. --version-comparison CMP semver May be 'debian', 'maven', 'naive', 'python', 'rpm', 'rubygem', or 'semver'. - --version true Version of the package + --version VERSION Version of the package -h, --help Print this help page Overview of ``display-config`` @@ -467,11 +467,11 @@ returns a page that looks something like this:: used more than once. -C, --card-file FILE ./out.dscard The name of the card file - -i, --id true ID (name) of the package - -l, --location true URL or filepath of the package + -i, --id ID ID (name) of the package + -l, --location LOCATION URL or filepath of the package -m, --meta K=V Add additional metadata -r, --requirement REQ List requirement ** - -v, --version true Version of the package + -v, --version VERSION Version of the package -h, --help Print this help page The following options are required for subcommand `generate-card`: diff --git a/src/degasolv/cli.clj b/src/degasolv/cli.clj index aaa392e..f4e3b6a 100644 --- a/src/degasolv/cli.clj +++ b/src/degasolv/cli.clj @@ -559,12 +559,12 @@ "ID (name) of the package" :validate [#(not (empty? %)) "ID must be a non-empty string."] - :required true] + ] ["-l" "--location LOCATION" "URL or filepath of the package" :validate [#(not (empty? %)) "Location must be a non-empty string."] - :required true] + ] ["-m" "--meta K=V" "Add additional metadata" :validate [#(re-matches #"^[^=]+=[^=].*$" %) @@ -585,7 +585,7 @@ "Version of the package" :validate [#(re-matches r/version-regex %) "Sorry, given argument doesn't look like a version."] - :required true] + ] ]} "generate-repo-index" {:description "Generate repository index based on degasolv package cards" From 11c56810e0ec2a4409b1ae88ff8d4e990e208bbc Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 12 Jun 2019 18:21:48 -0600 Subject: [PATCH 02/41] update changelog for #16 --- docs/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 4ca10a3..bf11cd4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -23,6 +23,7 @@ Changed Fixed +++++ +- Fix #16 `2.0.0`_ -------- From 7537ffa7291d7b1aa7d3baef76d549bd76ed7d4b Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 12 Jun 2019 18:24:19 -0600 Subject: [PATCH 03/41] Fix 3rd party licenses --- docs/3rd-party-licenses.rst | 368 ------------------------------------ 1 file changed, 368 deletions(-) diff --git a/docs/3rd-party-licenses.rst b/docs/3rd-party-licenses.rst index 0ce0eb2..ea5bcfd 100644 --- a/docs/3rd-party-licenses.rst +++ b/docs/3rd-party-licenses.rst @@ -6,374 +6,6 @@ Degasolv is built on the shoulders of giants. Here are the licenses for the third party software that comes with Degasolv. -Native-Image ------------- - -+------------------------------+--------------------------------------+ -| Software | `GraalVM Community Edition 19.0.0`_ | -+------------------------------+--------------------------------------+ -| Version of software | 19.0.0 | -+------------------------------+--------------------------------------+ -| Degasolv version introduced | 2.0.0 | -+------------------------------+--------------------------------------+ - -.. _GraalVM Community Edition 19.0.0: https://github.com/oracle/graal/releases/tag/vm-19.0.0 - -.. note:: Degasolv falls under Native-Image's "classpath exception" - and so does not need to conform to the license for Native-Image; - however, as a courtesy, its license is presented here. - -Verbatim License -++++++++++++++++ - -The GNU General Public License (GPL) - -Version 2, June 1991 - -Copyright (C) 1989, 1991 Free Software Foundation, Inc. -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Everyone is permitted to copy and distribute verbatim copies of this license -document, but changing it is not allowed. - -Preamble - -The licenses for most software are designed to take away your freedom to share -and change it. By contrast, the GNU General Public License is intended to -guarantee your freedom to share and change free software--to make sure the -software is free for all its users. This General Public License applies to -most of the Free Software Foundation's software and to any other program whose -authors commit to using it. (Some other Free Software Foundation software is -covered by the GNU Library General Public License instead.) You can apply it to -your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our -General Public Licenses are designed to make sure that you have the freedom to -distribute copies of free software (and charge for this service if you wish), -that you receive source code or can get it if you want it, that you can change -the software or use pieces of it in new free programs; and that you know you -can do these things. - -To protect your rights, we need to make restrictions that forbid anyone to deny -you these rights or to ask you to surrender the rights. These restrictions -translate to certain responsibilities for you if you distribute copies of the -software, or if you modify it. - -For example, if you distribute copies of such a program, whether gratis or for -a fee, you must give the recipients all the rights that you have. You must -make sure that they, too, receive or can get the source code. And you must -show them these terms so they know their rights. - -We protect your rights with two steps: (1) copyright the software, and (2) -offer you this license which gives you legal permission to copy, distribute -and/or modify the software. - -Also, for each author's protection and ours, we want to make certain that -everyone understands that there is no warranty for this free software. If the -software is modified by someone else and passed on, we want its recipients to -know that what they have is not the original, so that any problems introduced -by others will not reflect on the original authors' reputations. - -Finally, any free program is threatened constantly by software patents. We -wish to avoid the danger that redistributors of a free program will -individually obtain patent licenses, in effect making the program proprietary. -To prevent this, we have made it clear that any patent must be licensed for -everyone's free use or not licensed at all. - -The precise terms and conditions for copying, distribution and modification -follow. - -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - -0. This License applies to any program or other work which contains a notice -placed by the copyright holder saying it may be distributed under the terms of -this General Public License. The "Program", below, refers to any such program -or work, and a "work based on the Program" means either the Program or any -derivative work under copyright law: that is to say, a work containing the -Program or a portion of it, either verbatim or with modifications and/or -translated into another language. (Hereinafter, translation is included -without limitation in the term "modification".) Each licensee is addressed as -"you". - -Activities other than copying, distribution and modification are not covered by -this License; they are outside its scope. The act of running the Program is -not restricted, and the output from the Program is covered only if its contents -constitute a work based on the Program (independent of having been made by -running the Program). Whether that is true depends on what the Program does. - -1. You may copy and distribute verbatim copies of the Program's source code as -you receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice and -disclaimer of warranty; keep intact all the notices that refer to this License -and to the absence of any warranty; and give any other recipients of the -Program a copy of this License along with the Program. - -You may charge a fee for the physical act of transferring a copy, and you may -at your option offer warranty protection in exchange for a fee. - -2. You may modify your copy or copies of the Program or any portion of it, thus -forming a work based on the Program, and copy and distribute such modifications -or work under the terms of Section 1 above, provided that you also meet all of -these conditions: - - a) You must cause the modified files to carry prominent notices stating - that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in whole or - in part contains or is derived from the Program or any part thereof, to be - licensed as a whole at no charge to all third parties under the terms of - this License. - - c) If the modified program normally reads commands interactively when run, - you must cause it, when started running for such interactive use in the - most ordinary way, to print or display an announcement including an - appropriate copyright notice and a notice that there is no warranty (or - else, saying that you provide a warranty) and that users may redistribute - the program under these conditions, and telling the user how to view a copy - of this License. (Exception: if the Program itself is interactive but does - not normally print such an announcement, your work based on the Program is - not required to print an announcement.) - -These requirements apply to the modified work as a whole. If identifiable -sections of that work are not derived from the Program, and can be reasonably -considered independent and separate works in themselves, then this License, and -its terms, do not apply to those sections when you distribute them as separate -works. But when you distribute the same sections as part of a whole which is a -work based on the Program, the distribution of the whole must be on the terms -of this License, whose permissions for other licensees extend to the entire -whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest your -rights to work written entirely by you; rather, the intent is to exercise the -right to control the distribution of derivative or collective works based on -the Program. - -In addition, mere aggregation of another work not based on the Program with the -Program (or with a work based on the Program) on a volume of a storage or -distribution medium does not bring the other work under the scope of this -License. - -3. You may copy and distribute the Program (or a work based on it, under -Section 2) in object code or executable form under the terms of Sections 1 and -2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable source - code, which must be distributed under the terms of Sections 1 and 2 above - on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three years, to - give any third party, for a charge no more than your cost of physically - performing source distribution, a complete machine-readable copy of the - corresponding source code, to be distributed under the terms of Sections 1 - and 2 above on a medium customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer to - distribute corresponding source code. (This alternative is allowed only - for noncommercial distribution and only if you received the program in - object code or executable form with such an offer, in accord with - Subsection b above.) - -The source code for a work means the preferred form of the work for making -modifications to it. For an executable work, complete source code means all -the source code for all modules it contains, plus any associated interface -definition files, plus the scripts used to control compilation and installation -of the executable. However, as a special exception, the source code -distributed need not include anything that is normally distributed (in either -source or binary form) with the major components (compiler, kernel, and so on) -of the operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the source -code from the same place counts as distribution of the source code, even though -third parties are not compelled to copy the source along with the object code. - -4. You may not copy, modify, sublicense, or distribute the Program except as -expressly provided under this License. Any attempt otherwise to copy, modify, -sublicense or distribute the Program is void, and will automatically terminate -your rights under this License. However, parties who have received copies, or -rights, from you under this License will not have their licenses terminated so -long as such parties remain in full compliance. - -5. You are not required to accept this License, since you have not signed it. -However, nothing else grants you permission to modify or distribute the Program -or its derivative works. These actions are prohibited by law if you do not -accept this License. Therefore, by modifying or distributing the Program (or -any work based on the Program), you indicate your acceptance of this License to -do so, and all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - -6. Each time you redistribute the Program (or any work based on the Program), -the recipient automatically receives a license from the original licensor to -copy, distribute or modify the Program subject to these terms and conditions. -You may not impose any further restrictions on the recipients' exercise of the -rights granted herein. You are not responsible for enforcing compliance by -third parties to this License. - -7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), conditions -are imposed on you (whether by court order, agreement or otherwise) that -contradict the conditions of this License, they do not excuse you from the -conditions of this License. If you cannot distribute so as to satisfy -simultaneously your obligations under this License and any other pertinent -obligations, then as a consequence you may not distribute the Program at all. -For example, if a patent license would not permit royalty-free redistribution -of the Program by all those who receive copies directly or indirectly through -you, then the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply and -the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any patents or -other property right claims or to contest validity of any such claims; this -section has the sole purpose of protecting the integrity of the free software -distribution system, which is implemented by public license practices. Many -people have made generous contributions to the wide range of software -distributed through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing to -distribute software through any other system and a licensee cannot impose that -choice. - -This section is intended to make thoroughly clear what is believed to be a -consequence of the rest of this License. - -8. If the distribution and/or use of the Program is restricted in certain -countries either by patents or by copyrighted interfaces, the original -copyright holder who places the Program under this License may add an explicit -geographical distribution limitation excluding those countries, so that -distribution is permitted only in or among countries not thus excluded. In -such case, this License incorporates the limitation as if written in the body -of this License. - -9. The Free Software Foundation may publish revised and/or new versions of the -General Public License from time to time. Such new versions will be similar in -spirit to the present version, but may differ in detail to address new problems -or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any later -version", you have the option of following the terms and conditions either of -that version or of any later version published by the Free Software Foundation. -If the Program does not specify a version number of this License, you may -choose any version ever published by the Free Software Foundation. - -10. If you wish to incorporate parts of the Program into other free programs -whose distribution conditions are different, write to the author to ask for -permission. For software which is copyrighted by the Free Software Foundation, -write to the Free Software Foundation; we sometimes make exceptions for this. -Our decision will be guided by the two goals of preserving the free status of -all derivatives of our free software and of promoting the sharing and reuse of -software generally. - -NO WARRANTY - -11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR -THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE -STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE -PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND -PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, -YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - -12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL -ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE -PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR -INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA -BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER -OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -END OF TERMS AND CONDITIONS - -How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest possible -use to the public, the best way to achieve this is to make it free software -which everyone can redistribute and change under these terms. - -To do so, attach the following notices to the program. It is safest to attach -them to the start of each source file to most effectively convey the exclusion -of warranty; and each file should have at least the "copyright" line and a -pointer to where the full notice is found. - - One line to give the program's name and a brief idea of what it does. - - Copyright (C) - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this when it -starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author Gnomovision comes - with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free - software, and you are welcome to redistribute it under certain conditions; - type 'show c' for details. - -The hypothetical commands 'show w' and 'show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may be -called something other than 'show w' and 'show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your school, -if any, to sign a "copyright disclaimer" for the program, if necessary. Here -is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - 'Gnomovision' (which makes passes at compilers) written by James Hacker. - - signature of Ty Coon, 1 April 1989 - - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General Public -License instead of this License. - - -"CLASSPATH" EXCEPTION TO THE GPL - -Certain source files distributed by Oracle America and/or its affiliates are -subject to the following clarification and special exception to the GPL, but -only where Oracle has expressly included in the particular source file's header -the words "Oracle designates this particular file as subject to the "Classpath" -exception as provided by Oracle in the LICENSE file that accompanied this code." - - Linking this library statically or dynamically with other modules is making - a combined work based on this library. Thus, the terms and conditions of - the GNU General Public License cover the whole combination. - - As a special exception, the copyright holders of this library give you - permission to link this library with independent modules to produce an - executable, regardless of the license terms of these independent modules, - and to copy and distribute the resulting executable under terms of your - choice, provided that you also meet, for each linked independent module, - the terms and conditions of the license of that module. An independent - module is a module which is not derived from or based on this library. If - you modify this library, you may extend this exception to your version of - the library, but you are not obligated to do so. If you do not wish to do - so, delete this exception statement from your version. - Clojure and Clojure Libraries ----------------------------- From f005c4ad1a6e5499f8b708c193c2a8595001aaa9 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 12 Jun 2019 18:30:21 -0600 Subject: [PATCH 04/41] Bump version number --- docs/conf.py | 4 ++-- project.clj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 1864b10..aa94908 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -58,9 +58,9 @@ # built documents. # # The short X.Y version. -version = '2.0' +version = '2.1' # The full version, including alpha/beta/rc tags. -release = '2.0.0' +release = '2.1.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/project.clj b/project.clj index 019b150..c9f18ba 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject degasolv/degasolv "2.0.0" +(defproject degasolv/degasolv "2.1.0-SNAPSHOT" :description "Dependency tracker with an eye toward building and shipping software." :url "http://github.com/djhaskin987/degasolv" :license {:name "Eclipse Public License" From 26f9f842b477c9777d8879bc558fe3c78f3d46ac Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 12 Jun 2019 22:45:08 -0600 Subject: [PATCH 05/41] Housekeeping --- old-doc/README.md | 8 -- old-doc/cli_tutorial.md | 27 ---- old-doc/intro.md | 8 -- old-doc/old_tutorial.md | 297 ---------------------------------------- old-doc/recipes.md | 29 ---- old-doc/reference.md | 9 -- old-doc/tutorial.md | 297 ---------------------------------------- 7 files changed, 675 deletions(-) delete mode 100644 old-doc/README.md delete mode 100644 old-doc/cli_tutorial.md delete mode 100644 old-doc/intro.md delete mode 100644 old-doc/old_tutorial.md delete mode 100644 old-doc/recipes.md delete mode 100644 old-doc/reference.md delete mode 100644 old-doc/tutorial.md diff --git a/old-doc/README.md b/old-doc/README.md deleted file mode 100644 index 4777afa..0000000 --- a/old-doc/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Introduction to dependable - -Dependable is a library which provides functions hopefully useful for -purposes of dependency management. - -To get started quickly, see the [tutorial](https://github.com/djhaskin987/dependable/blob/develop/doc/tutorial.md). - -To view reference material, see the [reference guide](https://github.com/dependable/blob/develop/doc/reference.md). diff --git a/old-doc/cli_tutorial.md b/old-doc/cli_tutorial.md deleted file mode 100644 index b3b682a..0000000 --- a/old-doc/cli_tutorial.md +++ /dev/null @@ -1,27 +0,0 @@ -# CLI Tutorial (under contruction) - -so, - -```clojure -{ - :id "a" - :version "2.3.0" - :artifact-name "a-2.3.0.zip" - :location "http://example.com/repo/a-2.3.0.zip" - :sha256-sum "1cacb8cf7b1e00481019a4d76ba2b1c9511e11055329afd28272873d0a41499c" - :requirements - [[{:id "b" - :status :present - :spec [[{:relation :greater-equal - :version "0.3.0"}]]}]] -} -``` - -```clojure -{ - :id "b" - :version "0.4.0" - :artifact-name "b-3.2.4.zip" - - - diff --git a/old-doc/intro.md b/old-doc/intro.md deleted file mode 100644 index 4777afa..0000000 --- a/old-doc/intro.md +++ /dev/null @@ -1,8 +0,0 @@ -# Introduction to dependable - -Dependable is a library which provides functions hopefully useful for -purposes of dependency management. - -To get started quickly, see the [tutorial](https://github.com/djhaskin987/dependable/blob/develop/doc/tutorial.md). - -To view reference material, see the [reference guide](https://github.com/dependable/blob/develop/doc/reference.md). diff --git a/old-doc/old_tutorial.md b/old-doc/old_tutorial.md deleted file mode 100644 index 3d70b44..0000000 --- a/old-doc/old_tutorial.md +++ /dev/null @@ -1,297 +0,0 @@ -Quick Start -=========== - -So you're a Build engineer/DevOps engineer-ish, and you have a list of -dependencies, and you want to have them downloaded automatically as -part of a build. - -Suppose you have your artifacts, all zip files, stored on an -auto-indexed HTTP server at `http://example.com/repo/`. One of the -developer teams you support makes a component or microservice called -"A", and one makes a component or microservice called "B". In order to -compose them into a bigger artifact that you can actually deploy, you -need to download them into a build. - -Why use a dependency manager to do this? Well, probably because your -dependency tree is actually much bigger than just two -services/components. But this is a quickstart. - -**So, given these artifacts**: - - - `http://example.com/repo/a-1.0.zip` - - `http://example.com/repo/b-2.0.zip` - - `http://example.com/repo/b-3.0.zip` - -**You would publish an EDN file in the same directory, here**: - - - `http://example.com/repo/index.edn` - -**It might have these contents**: - -```clojure -{ - "a" - [{ - :id "a" - :version "1.0" - :location "http://example.com/repo/a-1.0.zip" - :requirements [[{:status :present :id "b" :spec [{:relation :greater-than :version "2.0"}]}]] - }] - "b" - [{ - :id "b" - :version "2.0" - :location "http://example.com/repo/b-2.0.zip" - } - { - :id "b" - :version "3.0" - :location "http://example.com/repo/b-3.0.zip" - }] -} -``` - -**Now, to get the URLs of the artifacts you should download if you -wish to download "A" and all its dependencies, you would write this**: - -```clojure -(ns my.namespace - (:require [dependable.resolver :refer :all])) - -;; ... - -(map :location - (resolve-dependencies - [[(present "a")]] - (map-query - (clojure.edn/read-string - (slurp "http://example.com/repo/index.edn"))) - :compare clj-semver.core/older?)) -``` - -**That little snippet would give you these results**: - -```clojure -[ - "http://example.com/repo/a-1.0.zip" - "http://example.com/repo/b-3.0.zip" -] -``` - -**Which URLs you could then use to download the artifacts and complete -the build.** - -Now, a longer example. -====================== - -The dependencies ----------------- - -So, you have a suite of builds for which you are responsible. These -builds kick out artifacts, which we will here call "components". These -components depend on each other's presence in order to build. That -dependency tree looks like this: - -![dependency graph](http://g.gravizo.com/g? - digraph G { - a -> b; - b -> c; - b -> d; - d -> e; - c -> e; -} -) - -For example, in order to build (and operate) component `a`, you must -first have `b`, `c`, `d`, and `e` present in the build directory. - -Well, *sort of*. You see, there was a recent breaking change to -`a`. Where `a@1.9` worked fine with all previous versions of `b`, the -newer `a@2.1` only works with `b@2.3` or greater. Since the `2.0` line of -`b` came out, it relies on the newer `c@3.5.2`, and the -ancient-but-still-used `d`, the only version of which was published as -`d@0.5`. The last time `d` was touched, the newest version of `e` was -`1.1`; however, the newer `c@3.5` relies on the fact that `e` must be -newer than `1.8`. There are three published versions of `e`: `e@1.8`, -`e@2.1`, and `e@2.4`. Only the `e@1.8` version of `e` is backwards -compatible with `e@1.1` and so it is the only version which will -satisfy all dependencies. - -See? THIS is why you use a dependency manager with your builds. - -Uploading a build ------------------ - -The first step is to build one of these dependencies. Let's say that -we have as part of this build already created `e`, at the brand new -version of `1.8`. We might have a file called `dependable.edn` somewhere -in our git repository for `e`. It might look like this: - -```clojure -{ - :id "e" - :version "1.8.0" - :file-name "e-1.8.0.zip" - :requirements [] -} -``` - -We will use this file to update the information of the downstream package repository like this: - -```clojure -(spit "new-repo-index.edn" - (let [e-information (clojure.edn/read-string (slurp "./dependable.edn"))] - (dependable.util/assoc-conj - (clojure.edn/read-string - (slurp "http://example.com/repo/index.edn")) - (:id information) - (assoc - (dissoc e-information :file-name) - :location - (str "http://example.com/repo/" (:file-name a-information)))))) -``` - -This new file could then be copied up to the HTTP server in place of the old file -located at `http://example.com/repo/index.edn`. - -So, to summarize: - - We've just built the package for `e`. - - After we build `e`, we update the repo metadata. - - We also upload the file associated - with `e` to the repo. In this case, it's `e-1.8.0.zip`. - -Let us now suppose that we have repeated these steps for all packages -mentioned above, except for the package `a`. The repo's `index.edn` -file might then look like this: - -```clojure -{ - "b" - [ - { - :id "b" - :version "1.7.0" - :location "http://example.com/repo/b-1.7.0.zip" - :requirements [] - } - { - :id "b" - :version "2.3.0" - :location "http://example.com/repo/b-2.4.0.zip" - :requirements [[{:status :present :id "c" :spec [{:relation :greater-equal :version "3.5"}]}]] - } - ] - "c" - [ - { - :id "c" - :version "2.4.7" - :location "http://example.com/repo/c-2.4.7.zip" - :requirements [] - } - { - :id "c" - :version "3.5.0" - :requirements [[{:status :present :id "e" :spec [{:relation :greater-equal :version "1.8"}]}]] - } - ] - "d" - [ - { - :id "d" - :version "0.8.0" - :location "http://example.com/repo/d-0.8.0.zip" - :requirements [[{:status :present :id "e" - :spec [ - {:relation :greater-equal :version "1.1"} - {:relation :less-than :version "2.0"}]}]] - } - ] - "e" - [ - { - :id "e" - :version "1.8.0" - :location "http://exmaple.com/repo/e-1.8.0.zip" - :requirements [] - } - { - :id "e" - :version "2.1.0" - :location "http://exmaple.com/repo/e-2.1.0.zip" - :requirements [] - } - { - :id "e" - :version "2.4.0" - :location "http://exmaple.com/repo/e-2.4.0.zip" - :requirements [] - } - ] -} -``` - -Resolving dependencies ----------------------- - -Now suppose that we are building `a`. In our example, `a` need not be -uploaded to the zip file repository, because `a` represents our final -product, and will be handed off to Project Management or Ops for later -release. We don't need it for any other builds, and so (in this -trivial example) we are not interested in uploading it to the repo. -But we are interested in resolving its dependencies, downloading them, -and using them to build the final product. - -Just like when we are uploading a package to the repository, we need a -file called something like `dependable.edn` in the root of the git -repository associated with building `a`. It might look like this: - -```clojure -{ - :id "a" - :version "2.1.0" - :file-name "a-2.1.0.zip" - :requirements [[{:status :present :id "b" :spec [{:relation :greater-than :version "2.0"}]}]] -} -``` - -With some minor arrangements, the code in the quickstart used to show how to -use the `resolve-dependencies` function will suffice here: - -``` -(ns my.namespace - (:require [dependable.resolver :refer :all])) - -;; ... - -(map :location - (resolve-dependencies - (:requirements - (clojure.edn/read-string - (slurp "dependable.edn"))) - (map-query - (clojure.edn/read-string - (slurp "http://example.com/repo/index.edn"))) - :compare clj-semver.core/older?)) -``` - -Or, alternatively, on the commandline: - -The following `map` function should return an array of locations -which can then be used to download artifacts needed for the build. In -our example, that should look like this: - -```clojure -[ - "http://example.com/repo/b-2.4.0.zip" - "http://example.com/repo/c-3.5.0.zip" - "http://example.com/repo/d-0.8.0.zip" - "http://exmaple.com/repo/e-1.8.0.zip" -] -``` - -# For more information - -To view reference material, see the [reference guide](https://github.com/dependable/blob/develop/doc/reference.md). - -To see how requirements works, see the [guide to the requirements parameter](https://github.com/dependable/blob/develop/doc/requirements.md). diff --git a/old-doc/recipes.md b/old-doc/recipes.md deleted file mode 100644 index 5577aa3..0000000 --- a/old-doc/recipes.md +++ /dev/null @@ -1,29 +0,0 @@ -Merging two repository datastructures -===================================== - -```clojure -(merge-with - (fn [x y] - (sort - #(cmp (:version %1) (:version %2)) - (concat x y))) - (clojure.edn/read-str (slurp "./index-dee.edn")) - (clojure.edn/read-str (slurp "./index-dum.edn"))) -``` - -Adding a record to a repository index -===================================== - -```clojure -(let [new-record (clojure.edn/read-str (slurp "./dependable.edn"))] - (update-in - (clojure.edn/read-str (slurp "url-to-index.edn")) - [(:id new-record)] - conj - new-record)) -``` - -Managed dependencies -==================== - -Under Construction. diff --git a/old-doc/reference.md b/old-doc/reference.md deleted file mode 100644 index d5642f0..0000000 --- a/old-doc/reference.md +++ /dev/null @@ -1,9 +0,0 @@ -# Reference Guide -## `resolve-dependencies` -**Signature:** -```clojure - -## `single-requirement` -## `absent` -## `present` -## `map-repo` diff --git a/old-doc/tutorial.md b/old-doc/tutorial.md deleted file mode 100644 index 3d70b44..0000000 --- a/old-doc/tutorial.md +++ /dev/null @@ -1,297 +0,0 @@ -Quick Start -=========== - -So you're a Build engineer/DevOps engineer-ish, and you have a list of -dependencies, and you want to have them downloaded automatically as -part of a build. - -Suppose you have your artifacts, all zip files, stored on an -auto-indexed HTTP server at `http://example.com/repo/`. One of the -developer teams you support makes a component or microservice called -"A", and one makes a component or microservice called "B". In order to -compose them into a bigger artifact that you can actually deploy, you -need to download them into a build. - -Why use a dependency manager to do this? Well, probably because your -dependency tree is actually much bigger than just two -services/components. But this is a quickstart. - -**So, given these artifacts**: - - - `http://example.com/repo/a-1.0.zip` - - `http://example.com/repo/b-2.0.zip` - - `http://example.com/repo/b-3.0.zip` - -**You would publish an EDN file in the same directory, here**: - - - `http://example.com/repo/index.edn` - -**It might have these contents**: - -```clojure -{ - "a" - [{ - :id "a" - :version "1.0" - :location "http://example.com/repo/a-1.0.zip" - :requirements [[{:status :present :id "b" :spec [{:relation :greater-than :version "2.0"}]}]] - }] - "b" - [{ - :id "b" - :version "2.0" - :location "http://example.com/repo/b-2.0.zip" - } - { - :id "b" - :version "3.0" - :location "http://example.com/repo/b-3.0.zip" - }] -} -``` - -**Now, to get the URLs of the artifacts you should download if you -wish to download "A" and all its dependencies, you would write this**: - -```clojure -(ns my.namespace - (:require [dependable.resolver :refer :all])) - -;; ... - -(map :location - (resolve-dependencies - [[(present "a")]] - (map-query - (clojure.edn/read-string - (slurp "http://example.com/repo/index.edn"))) - :compare clj-semver.core/older?)) -``` - -**That little snippet would give you these results**: - -```clojure -[ - "http://example.com/repo/a-1.0.zip" - "http://example.com/repo/b-3.0.zip" -] -``` - -**Which URLs you could then use to download the artifacts and complete -the build.** - -Now, a longer example. -====================== - -The dependencies ----------------- - -So, you have a suite of builds for which you are responsible. These -builds kick out artifacts, which we will here call "components". These -components depend on each other's presence in order to build. That -dependency tree looks like this: - -![dependency graph](http://g.gravizo.com/g? - digraph G { - a -> b; - b -> c; - b -> d; - d -> e; - c -> e; -} -) - -For example, in order to build (and operate) component `a`, you must -first have `b`, `c`, `d`, and `e` present in the build directory. - -Well, *sort of*. You see, there was a recent breaking change to -`a`. Where `a@1.9` worked fine with all previous versions of `b`, the -newer `a@2.1` only works with `b@2.3` or greater. Since the `2.0` line of -`b` came out, it relies on the newer `c@3.5.2`, and the -ancient-but-still-used `d`, the only version of which was published as -`d@0.5`. The last time `d` was touched, the newest version of `e` was -`1.1`; however, the newer `c@3.5` relies on the fact that `e` must be -newer than `1.8`. There are three published versions of `e`: `e@1.8`, -`e@2.1`, and `e@2.4`. Only the `e@1.8` version of `e` is backwards -compatible with `e@1.1` and so it is the only version which will -satisfy all dependencies. - -See? THIS is why you use a dependency manager with your builds. - -Uploading a build ------------------ - -The first step is to build one of these dependencies. Let's say that -we have as part of this build already created `e`, at the brand new -version of `1.8`. We might have a file called `dependable.edn` somewhere -in our git repository for `e`. It might look like this: - -```clojure -{ - :id "e" - :version "1.8.0" - :file-name "e-1.8.0.zip" - :requirements [] -} -``` - -We will use this file to update the information of the downstream package repository like this: - -```clojure -(spit "new-repo-index.edn" - (let [e-information (clojure.edn/read-string (slurp "./dependable.edn"))] - (dependable.util/assoc-conj - (clojure.edn/read-string - (slurp "http://example.com/repo/index.edn")) - (:id information) - (assoc - (dissoc e-information :file-name) - :location - (str "http://example.com/repo/" (:file-name a-information)))))) -``` - -This new file could then be copied up to the HTTP server in place of the old file -located at `http://example.com/repo/index.edn`. - -So, to summarize: - - We've just built the package for `e`. - - After we build `e`, we update the repo metadata. - - We also upload the file associated - with `e` to the repo. In this case, it's `e-1.8.0.zip`. - -Let us now suppose that we have repeated these steps for all packages -mentioned above, except for the package `a`. The repo's `index.edn` -file might then look like this: - -```clojure -{ - "b" - [ - { - :id "b" - :version "1.7.0" - :location "http://example.com/repo/b-1.7.0.zip" - :requirements [] - } - { - :id "b" - :version "2.3.0" - :location "http://example.com/repo/b-2.4.0.zip" - :requirements [[{:status :present :id "c" :spec [{:relation :greater-equal :version "3.5"}]}]] - } - ] - "c" - [ - { - :id "c" - :version "2.4.7" - :location "http://example.com/repo/c-2.4.7.zip" - :requirements [] - } - { - :id "c" - :version "3.5.0" - :requirements [[{:status :present :id "e" :spec [{:relation :greater-equal :version "1.8"}]}]] - } - ] - "d" - [ - { - :id "d" - :version "0.8.0" - :location "http://example.com/repo/d-0.8.0.zip" - :requirements [[{:status :present :id "e" - :spec [ - {:relation :greater-equal :version "1.1"} - {:relation :less-than :version "2.0"}]}]] - } - ] - "e" - [ - { - :id "e" - :version "1.8.0" - :location "http://exmaple.com/repo/e-1.8.0.zip" - :requirements [] - } - { - :id "e" - :version "2.1.0" - :location "http://exmaple.com/repo/e-2.1.0.zip" - :requirements [] - } - { - :id "e" - :version "2.4.0" - :location "http://exmaple.com/repo/e-2.4.0.zip" - :requirements [] - } - ] -} -``` - -Resolving dependencies ----------------------- - -Now suppose that we are building `a`. In our example, `a` need not be -uploaded to the zip file repository, because `a` represents our final -product, and will be handed off to Project Management or Ops for later -release. We don't need it for any other builds, and so (in this -trivial example) we are not interested in uploading it to the repo. -But we are interested in resolving its dependencies, downloading them, -and using them to build the final product. - -Just like when we are uploading a package to the repository, we need a -file called something like `dependable.edn` in the root of the git -repository associated with building `a`. It might look like this: - -```clojure -{ - :id "a" - :version "2.1.0" - :file-name "a-2.1.0.zip" - :requirements [[{:status :present :id "b" :spec [{:relation :greater-than :version "2.0"}]}]] -} -``` - -With some minor arrangements, the code in the quickstart used to show how to -use the `resolve-dependencies` function will suffice here: - -``` -(ns my.namespace - (:require [dependable.resolver :refer :all])) - -;; ... - -(map :location - (resolve-dependencies - (:requirements - (clojure.edn/read-string - (slurp "dependable.edn"))) - (map-query - (clojure.edn/read-string - (slurp "http://example.com/repo/index.edn"))) - :compare clj-semver.core/older?)) -``` - -Or, alternatively, on the commandline: - -The following `map` function should return an array of locations -which can then be used to download artifacts needed for the build. In -our example, that should look like this: - -```clojure -[ - "http://example.com/repo/b-2.4.0.zip" - "http://example.com/repo/c-3.5.0.zip" - "http://example.com/repo/d-0.8.0.zip" - "http://exmaple.com/repo/e-1.8.0.zip" -] -``` - -# For more information - -To view reference material, see the [reference guide](https://github.com/dependable/blob/develop/doc/reference.md). - -To see how requirements works, see the [guide to the requirements parameter](https://github.com/dependable/blob/develop/doc/requirements.md). From 344a4a50d84e1f81235f08afb8959b140b1980e0 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 12 Jun 2019 22:45:52 -0600 Subject: [PATCH 06/41] Housekeeping --- TODO | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 TODO diff --git a/TODO b/TODO deleted file mode 100644 index 5b91ba3..0000000 --- a/TODO +++ /dev/null @@ -1,3 +0,0 @@ -- [ ] Docs: common pitfall of subproc: "name" vs "id" in json or - strings vs keywords in EDN -- [ ] 2.0.0 release: run test scripts on graal output as part of the build From 0fa0f2feb1487d13ec30fa6b0d1cd9a729697182 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Thu, 22 Aug 2019 12:20:58 -0600 Subject: [PATCH 07/41] Add roadmap --- docs/index.rst | 1 + docs/roadmap.rst | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 docs/roadmap.rst diff --git a/docs/index.rst b/docs/index.rst index 661f544..38d8103 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,6 +26,7 @@ Fork Degasolv on Github: Command Reference Code of Conduct Contributing Guide + Roadmap Authors and Contributions 3rd Party Licenses <3rd-party-licenses> diff --git a/docs/roadmap.rst b/docs/roadmap.rst new file mode 100644 index 0000000..f82b7e7 --- /dev/null +++ b/docs/roadmap.rst @@ -0,0 +1,22 @@ +Roadmap +======= + +This document is intended to help guide what features are upcoming in degasolv. +Some of these features are aspirational; that is, we want to implement them, +but may not be able to or may decide later that we didn't really want that +after all. Nevertheless, for what it's worth, here is the current roadmap. + +2.1.0 +----- +- **Catch and release**: Catch failed clause resolutions early when the failed + clause's package name in a recursive call matches the present clause. This + should significantly speed up clause resolution and make the idea of minimum + version selection possible. +- **Minimum Version Selection**: Implement minimum version selection by + introducing an option into resolve-locations that instructs degasolv which to + choose: the smallest version available or the largest. + +Future Features +--------------- +- **Compile with GraalVM's ``native-image``**: Compile degasolv to machine + code with GraalVM's ``native-image`` to decrease start-up times. From df9230a972e229d3d47cfd17f6a48ba6a90e9b52 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Thu, 22 Aug 2019 15:46:39 -0600 Subject: [PATCH 08/41] Try to simplify code a little --- docs/changelog.rst | 2 + src/degasolv/resolver_core.clj | 634 ++++++++++--------- test/degasolv/resolver/core_test.clj | 102 +-- test/degasolv/resolver/search_strat_test.clj | 14 +- 4 files changed, 381 insertions(+), 371 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index bf11cd4..355fdb7 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -20,6 +20,8 @@ Added Changed +++++++ +- Removed the deprecated functions ``->requirement``, ``->package``, and ``->version-predicate`` from usage in the code base. + Fixed +++++ diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index 62351d5..e8a936e 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -22,35 +22,30 @@ Object (toString [this] (str - ((:relation this) relation-strings) - version))) + ((:relation this) relation-strings) + version))) (defrecord Requirement [status id spec] Object (toString [this] (str - (if (= (:status this) :absent) - "!" - "") - (:id this) - (clj-str/join - ";" - (map - (fn conjoin-preds [conjunction] - (clj-str/join - "," - (map - #(str %) - conjunction))) - (:spec this)))))) + (if (= (:status this) :absent) + "!" + "") + (:id this) + (clj-str/join + ";" + (map + (fn conjoin-preds [conjunction] + (clj-str/join + "," + (map + #(str %) + conjunction))) + (:spec this)))))) (defrecord PackageInfo [id version location requirements]) -;; Deprecated, do not use -(def ->requirement ->Requirement) -(def ->package ->PackageInfo) -(def ->version-predicate ->VersionPredicate) - (defmethod print-method degasolv.resolver.PackageInfo @@ -96,20 +91,20 @@ (defn- make-comparison [cmp pkg-ver relation version] (if (= relation :matches) (if-let [pattern (try (re-pattern version) - (catch Exception e - false))] + (catch Exception e + false))] (re-matches pattern pkg-ver) false) (let [cmp-result (cmp pkg-ver version)] (cond (= relation - :in-range) + :in-range) (if-let [[_ rest re-num _] (re-find #"^(.*?)(\d+)(\D*)$" version)] (let [num (java.lang.Integer/parseInt re-num) higher-version (str rest (inc num)) higher-result (cmp pkg-ver higher-version)] (and (>= cmp-result 0) - (< higher-result 0))) + (< higher-result 0))) false) (= relation :pess-greater) @@ -121,9 +116,9 @@ strnum (first nums) intnum (java.lang.Integer/parseInt strnum) higher-result (as-> intnum it - (inc it) - (str (first non-nums) it) - (cmp pkg-ver it))] + (inc it) + (str (first non-nums) it) + (cmp pkg-ver it))] (and (>= cmp-result 0) (< higher-result 0)))) :else @@ -155,19 +150,19 @@ true (let [pkg-ver (:version present-package)] (reduce - (fn [disj-cum disj-val] - (or disj-cum - (reduce - (fn [conj-cum {:keys [relation version]}] - (and conj-cum - (make-comparison - cmp - pkg-ver - relation - version))) - true disj-val))) - false - spec))))) + (fn [disj-cum disj-val] + (or disj-cum + (reduce + (fn [conj-cum {:keys [relation version]}] + (and conj-cum + (make-comparison + cmp + pkg-ver + relation + version))) + true disj-val))) + false + spec))))) (defn- aggregate-attempts [c v] (conj c v)) @@ -191,24 +186,24 @@ alternatives (let [partn (group-by - (fn [term] - (let [id (get term :id)] - (cond - (get - absent-specs - id) - :absent - (or - (get - found-packages - id) + (fn [term] + (let [id (get term :id)] + (cond (get - present-packages - id)) - :present - :else - :unspecified))) - alternatives) + absent-specs + id) + :absent + (or + (get + found-packages + id) + (get + present-packages + id)) + :present + :else + :unspecified))) + alternatives) result (concat (:absent partn) (:present partn) (:unspecified partn))] result))) @@ -221,14 +216,14 @@ (defn- first-found [f pred coll] (reduce - (fn find-first - [c v] - (let [new-v (f v)] - (if (pred new-v) - (reduced [new-v]) - (conj c new-v)))) - [] - coll)) + (fn find-first + [c v] + (let [new-v (f v)] + (if (pred new-v) + (reduced [new-v]) + (conj c new-v)))) + [] + coll)) ;; Does one of the present packages already ;; satisfy criteria? If so, return it. @@ -238,19 +233,19 @@ safe-spec-call status] (some - #(when (not (nil? %)) %) - (map - (fn [pkg] - (let [present-package-test - (safe-spec-call - spec - pkg)] - (when (or (and (= status :absent) - (not present-package-test)) - (and (= status :present) - present-package-test)) - pkg))) - pkgs))) + #(when (not (nil? %)) %) + (map + (fn [pkg] + (let [present-package-test + (safe-spec-call + spec + pkg)] + (when (or (and (= status :absent) + (not present-package-test)) + (and (= status :present) + present-package-test)) + pkg))) + pkgs))) ;; root -> a ;; root -> x @@ -268,9 +263,9 @@ parents children-of] (let [children (filter - #(and - (not (get already-visited %)) - (not (get parents %))) + #(and + (not (get already-visited %)) + (not (get parents %))) (get package-graph children-of))] (if (empty? children) {:pkg-list [] @@ -287,8 +282,8 @@ pkg-list grandchildren-list) base-visited (into - visited - grandchildren-visited)] + visited + grandchildren-visited)] (if (and (= list-strat :eager) (not (get base-visited v))) {:pkg-list (conj base-pkg-list v) @@ -308,6 +303,219 @@ (let [{:keys [pkg-list visited]} (list-pkgs-rec #{} #{:root} :root)] pkg-list))) +(defn make-resolve-deps + [conflict-strat + concat-reqs + safe-spec-call + cull + cull-alternatives] + (fn resolve-deps + [repo + present-packages + found-packages + absent-specs + clauses + package-graph] + (if (empty? clauses) + [:successful + package-graph] + (let [fclause (first clauses) + rclauses (rest clauses) + {:keys [clause parent]} + fclause] + (if (empty? clause) + [:unsuccessful + {:problems + [{:term clause + :found-packages found-packages + :present-packages present-packages + :absent-specs absent-specs + :reason :empty-alternative-set}]}] + (let [clause-result + (first-found + (fn try-alternative + [alternative] + (let [{status :status id :id spec :spec} + alternative + present-id-packages + (get present-packages id) + found-id-packages + (get found-packages id) + get-pkg-exists + (fn get-pkg-exists [pkgs] + (when (not (nil? pkgs)) + (if (= conflict-strat :prioritized) + (first pkgs) + (present-packages-satisfies? + pkgs + spec + safe-spec-call + status)))) + present-package + (get-pkg-exists present-id-packages) + found-package + (get-pkg-exists found-id-packages)] + (cond + (not + (nil? present-package)) + (resolve-deps + repo + present-packages + found-packages + absent-specs + rclauses + package-graph) + (not + (nil? found-package)) + (resolve-deps + repo + present-packages + found-packages + absent-specs + rclauses + (update-in package-graph + [parent] + #(if (empty? %1) + (do [%2]) + (conj %1 %2)) + found-package)) + (and (or + (not (nil? found-id-packages)) + (not (nil? present-id-packages))) + (not (= conflict-strat :inclusive))) + [:unsuccessful + {:problems + [ + {:term clause + :found-packages found-packages + :present-packages present-packages + :absent-specs absent-specs + :reason :present-package-conflict + :alternative alternative + :package-id id}]}] + (= status :absent) + (resolve-deps + repo + present-packages + found-packages + (update-in absent-specs + [id] + #(if (empty? %1) + (do [%2]) + (conj %1 %2)) + spec) + rclauses + package-graph) + (= status :present) + (let [query-results (repo id)] + (if (empty? query-results) + [:unsuccessful + {:problems + [ + {:term clause + :alternative alternative + :found-packages found-packages + :present-packages present-packages + :absent-specs absent-specs + :reason :package-not-found + :package-id id}]}] + (let [filtered-query-results + (cull + (filter + (fn vet-candidate + [candidate] + (and + (safe-spec-call spec candidate) + (reduce + (fn [x y] + (and + x + (not + (safe-spec-call + y + candidate)))) + true + (get absent-specs id)))) + query-results))] + (if (empty? filtered-query-results) + [:unsuccessful + {:problems + [{:term clause + :alternative alternative + :found-packages found-packages + :present-packages present-packages + :absent-specs absent-specs + :reason :package-rejected + :package-id id}]}] + (let [candidate-results + (first-found + (fn + try-candidate + [candidate] + (resolve-deps + repo + present-packages + (update-in found-packages + [id] + #(if (empty? %1) + (do [%2]) + (conj %1 %2)) + candidate) + absent-specs + (concat-reqs + rclauses + (map + #(->DecoratedRequirement + % + candidate) + (:requirements + candidate))) + (update-in package-graph + [parent] + #(if (empty? %1) + (do [%2]) + (conj %1 %2)) + candidate))) + successful? + filtered-query-results)] + (or + (some + first-successful + candidate-results) + [:unsuccessful + {:problems + (flatten + (map + #(:problems + (get % 1)) + candidate-results))}])))))) + :else + [:unsuccessful {:problems + [{:term clause + :reason :uncovered-case + :alternative alternative + :found-packages found-packages + :present-packages present-packages + :absent-specs absent-specs}]}]))) + successful? + ;; Hoisting + (hoist (cull-alternatives + clause) + absent-specs + found-packages + present-packages))] + (or + (some + first-successful + clause-result) + [:unsuccessful + {:problems + (flatten + (map + #(:problems + (get % 1)) + clause-result))}]))))))) + (defn resolve-dependencies [requirements query & {:keys [present-packages @@ -337,237 +545,37 @@ :fast cull-all-but-first (throw - (ex-info (str - "Invalid strategy `" - strategy - "`.") - {:strategy strategy}))) + (ex-info (str + "Invalid strategy `" + strategy + "`.") + {:strategy strategy}))) cull-alternatives (if allow-alternatives cull-nothing - cull-all-but-first)] - (letfn [(resolve-deps - [repo - present-packages - found-packages - absent-specs - clauses - package-graph] - (if (empty? clauses) - [:successful - package-graph] - (let [fclause (first clauses) - rclauses (rest clauses) - {:keys [clause parent]} - fclause] - (if (empty? clause) - [:unsuccessful - {:problems - [{:term clause - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs - :reason :empty-alternative-set}]}] - (let [clause-result - (first-found - (fn try-alternative - [alternative] - (let [{status :status id :id spec :spec} - alternative - present-id-packages - (get present-packages id) - found-id-packages - (get found-packages id) - get-pkg-exists - (fn get-pkg-exists [pkgs] - (when (not (nil? pkgs)) - (if (= conflict-strat :prioritized) - (first pkgs) - (present-packages-satisfies? - pkgs - spec - safe-spec-call - status)))) - present-package - (get-pkg-exists present-id-packages) - found-package - (get-pkg-exists found-id-packages)] - (cond - (not - (nil? present-package)) - (resolve-deps - repo - present-packages - found-packages - absent-specs - rclauses - package-graph) - (not - (nil? found-package)) - (resolve-deps - repo - present-packages - found-packages - absent-specs - rclauses - (update-in package-graph - [parent] - #(if (empty? %1) - (do [%2]) - (conj %1 %2)) - found-package)) - (and (or - (not (nil? found-id-packages)) - (not (nil? present-id-packages))) - (not (= conflict-strat :inclusive))) - [:unsuccessful - {:problems - [ - {:term clause - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs - :reason :present-package-conflict - :alternative alternative - :package-id id}]}] - (= status :absent) - (resolve-deps - repo - present-packages - found-packages - (update-in absent-specs - [id] - #(if (empty? %1) - (do [%2]) - (conj %1 %2)) - spec) - rclauses - package-graph) - (= status :present) - (let [query-results (repo id)] - (if (empty? query-results) - [:unsuccessful - {:problems - [ - {:term clause - :alternative alternative - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs - :reason :package-not-found - :package-id id}]}] - (let [filtered-query-results - (cull - (filter - (fn vet-candidate - [candidate] - (and - (safe-spec-call spec candidate) - (reduce - (fn [x y] - (and - x - (not - (safe-spec-call - y - candidate)))) - true - (get absent-specs id)))) - query-results))] - (if (empty? filtered-query-results) - [:unsuccessful - {:problems - [{:term clause - :alternative alternative - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs - :reason :package-rejected - :package-id id}]}] - (let [candidate-results - (first-found - (fn - try-candidate - [candidate] - (resolve-deps - repo - present-packages - (update-in found-packages - [id] - #(if (empty? %1) - (do [%2]) - (conj %1 %2)) - candidate) - absent-specs - (concat-reqs - rclauses - (map - #(->DecoratedRequirement - % - candidate) - (:requirements - candidate))) - (update-in package-graph - [parent] - #(if (empty? %1) - (do [%2]) - (conj %1 %2)) - candidate))) - successful? - filtered-query-results)] - (or - (some - first-successful - candidate-results) - [:unsuccessful - {:problems - (flatten - (map - #(:problems - (get % 1)) - candidate-results))}])))))) - :else - [:unsuccessful {:problems - [{:term clause - :reason :uncovered-case - :alternative alternative - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs}]}]))) - successful? - ;; Hoisting - (hoist (cull-alternatives - clause) - absent-specs - found-packages - present-packages))] - (or - (some - first-successful - clause-result) - [:unsuccessful - {:problems - (flatten - (map - #(:problems - (get % 1)) - clause-result))}]))))))] - (let [result - (resolve-deps - query - present-packages - {} - conflicts - (map #(->DecoratedRequirement % :root) requirements) - {})] - (if (= :successful (first result)) - [:successful - (if (= :as-set list-strat) - (set - (list-packages + cull-all-but-first) + resolve-deps (make-resolve-deps + conflict-strat + concat-reqs + safe-spec-call + cull + cull-alternatives)] + (let [result + (resolve-deps + query + present-packages + {} + conflicts + (map #(->DecoratedRequirement % :root) requirements) + {})] + (if (= :successful (first result)) + [:successful + (if (= :as-set list-strat) + (set + (list-packages (second result) :list-strat :lazy)) - (list-packages - (second result) - :list-strat list-strat))] - result))))) + (list-packages + (second result) + :list-strat list-strat))] + result)))) diff --git a/test/degasolv/resolver/core_test.clj b/test/degasolv/resolver/core_test.clj index a8f4b00..c73a59f 100644 --- a/test/degasolv/resolver/core_test.clj +++ b/test/degasolv/resolver/core_test.clj @@ -10,7 +10,7 @@ ;; TODO: disjunctive clause tests (let [package-a30 - (->package + (->PackageInfo "a" 30 "a_loc30" @@ -18,25 +18,25 @@ [(present "c")] ]) package-a20 - (->package + (->PackageInfo "a" 20 "a_loc20" nil) package-c10 - (->package + (->PackageInfo "c" 10 "c_loc10" nil) package-d22 - (->package + (->PackageInfo "d" 22 "d_loc22" nil) package-e18 - (->package + (->PackageInfo "e" 18 "e_loc18" @@ -143,7 +143,7 @@ ] query :present-packages {"b" - [(->package "b" 10 "b-loc10" nil)]})))) + [(->PackageInfo "b" 10 "b-loc10" nil)]})))) (testing (str "Asking to install a package that is already " "installed, but the installed version doesn't " @@ -198,7 +198,7 @@ (deftest ^:unit-tests requires (let [package-a - (->package + (->PackageInfo "a" 30 "a_loc30" @@ -206,7 +206,7 @@ [(present "b")] ]) package-b - (->package + (->PackageInfo "b" 20 "b_loc20" @@ -235,13 +235,13 @@ query :present-packages {"b" [package-b]}))))) (let [package-a - (->package + (->PackageInfo "a" 10 "a_loc10" nil) package-b - (->package + (->PackageInfo "b" 20 "b_loc20" @@ -249,7 +249,7 @@ [(present "c")] ]) package-c - (->package + (->PackageInfo "c" 10 "c_loc10" @@ -276,13 +276,13 @@ ] query)))))) (let [package-a - (->package + (->PackageInfo "a" 10 "a_loc10" nil) package-b - (->package + (->PackageInfo "b" 10 "b_loc10" @@ -291,7 +291,7 @@ ] ) package-c - (->package + (->PackageInfo "c" 10 "c_loc10" @@ -329,7 +329,7 @@ (testing "Skip past a conflict" (let [package-a - (->package + (->PackageInfo "a" 30 "a_loc30" @@ -337,7 +337,7 @@ [(present "b")] ]) package-b - (->package + (->PackageInfo "b" 20 "b_loc20" @@ -352,14 +352,14 @@ [(absent "c") (present "b")] ] query - :present-packages {"c" [(->package "c" 10 "c_loc10" nil)]})))))) + :present-packages {"c" [(->PackageInfo "c" 10 "c_loc10" nil)]})))))) (deftest ^:unit-tests no-locking (testing (str "Find two packages, even when the preferred version " "of one package conflicts with the other") (let [package-a30 - (->package + (->PackageInfo "a" 30 "a_loc30" @@ -367,13 +367,13 @@ [(absent "c")] ]) package-a20 - (->package + (->PackageInfo "a" 20 "a_loc20" nil) package-c10 - (->package + (->PackageInfo "c" 10 "c_loc10" @@ -391,7 +391,7 @@ query))))) (testing (str "Diamond problem") (let [package-a - (->package + (->PackageInfo "a" 1 "a_loc1" @@ -401,7 +401,7 @@ ] ) package-b - (->package + (->PackageInfo "b" 1 "b_loc1" @@ -412,7 +412,7 @@ ] ) package-c - (->package + (->PackageInfo "c" 1 "c_loc1" @@ -423,13 +423,13 @@ ] ) package-d3 - (->package + (->PackageInfo "d" 3 "d_loc3" nil) package-d4 - (->package + (->PackageInfo "d" 4 "d_loc4" @@ -451,7 +451,7 @@ query))))) (testing (str "Inter-Locking Diamond problem") (let [package-a - (->package + (->PackageInfo "a" 1 "a_loc1" @@ -461,7 +461,7 @@ ] ) package-b - (->package + (->PackageInfo "b" 1 "b_loc1" @@ -471,7 +471,7 @@ ] ) package-c - (->package + (->PackageInfo "c" 1 "c_loc1" @@ -481,25 +481,25 @@ ] ) package-d3 - (->package + (->PackageInfo "d" 3 "d_loc3" nil) package-d4 - (->package + (->PackageInfo "d" 4 "d_loc4" nil) package-e6 - (->package + (->PackageInfo "e" 6 "e_loc6" nil) package-e5 - (->package + (->PackageInfo "e" 5 "e_loc5" @@ -526,7 +526,7 @@ )))) (testing (str "The puzzle") (let [package-a - (->package + (->PackageInfo "a" 1 "a_loc1" @@ -536,7 +536,7 @@ ] ) package-b - (->package + (->PackageInfo "b" 1 "b_loc1" @@ -545,7 +545,7 @@ ] ) package-c - (->package + (->PackageInfo "c" 1 "c_loc1" @@ -554,7 +554,7 @@ ] ) package-d1 - (->package + (->PackageInfo "d" 1 "d_loc1" @@ -563,7 +563,7 @@ ] ) package-d2 - (->package + (->PackageInfo "d" 2 "d_loc2" @@ -572,13 +572,13 @@ ] ) package-e4 - (->package + (->PackageInfo "e" 4 "e_loc4" nil) package-e3 - (->package + (->PackageInfo "3" 3 "e_loc3" @@ -603,7 +603,7 @@ query))))) (testing (str "Double diamond") (let [package-a - (->package + (->PackageInfo "a" 1 "a_loc1" @@ -613,7 +613,7 @@ ] ) package-b - (->package + (->PackageInfo "b" 1 "b_loc1" @@ -623,7 +623,7 @@ ] ) package-c - (->package + (->PackageInfo "c" 1 "c_loc1" @@ -632,19 +632,19 @@ ] ) package-d4 - (->package + (->PackageInfo "d" 4 "d_loc4" nil) package-d3 - (->package + (->PackageInfo "d" 3 "d_loc3" nil) package-d2 - (->package + (->PackageInfo "d" 2 "d_loc2" @@ -666,7 +666,7 @@ (deftest ^:resolve-basic hoisting (let [package-a - (->package + (->PackageInfo "a" 1 "a_loc1" @@ -675,7 +675,7 @@ ] ) package-b - (->package + (->PackageInfo "b" 1 "b_loc1" @@ -685,13 +685,13 @@ ] ) package-c - (->package + (->PackageInfo "c" 1 "c_loc1" nil) package-d - (->package + (->PackageInfo "d" 1 "d_loc1" @@ -731,7 +731,7 @@ (deftest ^:unit-tests circular-dependencies (testing "circular dependencies" (let [package-a - (->package + (->PackageInfo "a" 30 "a_loc30" @@ -739,7 +739,7 @@ [(present "b")] ]) package-b - (->package + (->PackageInfo "b" 20 "b_loc20" diff --git a/test/degasolv/resolver/search_strat_test.clj b/test/degasolv/resolver/search_strat_test.clj index 8112bed..096d53d 100644 --- a/test/degasolv/resolver/search_strat_test.clj +++ b/test/degasolv/resolver/search_strat_test.clj @@ -11,7 +11,7 @@ (deftest ^:unit-tests basic-dfs (testing "Make sure ``the puzzle`` still works" (let [package-a - (->package + (->PackageInfo "a" 1 "a_loc1" @@ -21,7 +21,7 @@ ] ) package-b - (->package + (->PackageInfo "b" 1 "b_loc1" @@ -30,7 +30,7 @@ ] ) package-c - (->package + (->PackageInfo "c" 1 "c_loc1" @@ -39,7 +39,7 @@ ] ) package-d1 - (->package + (->PackageInfo "d" 1 "d_loc1" @@ -48,7 +48,7 @@ ] ) package-d2 - (->package + (->PackageInfo "d" 2 "d_loc2" @@ -57,13 +57,13 @@ ] ) package-e4 - (->package + (->PackageInfo "e" 4 "e_loc4" nil) package-e3 - (->package + (->PackageInfo "3" 3 "e_loc3" From 10d13d3e49cf2ab252b33bd005a6bb5827c6e8f0 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Fri, 23 Aug 2019 13:45:26 -0600 Subject: [PATCH 09/41] Switch some dependencies in preparation for clj-http --- project.clj | 13 ++++---- src/degasolv/cli.clj | 44 +++++++++++++------------ src/degasolv/pkgsys/git.clj | 13 ++++++++ src/degasolv/pkgsys/subproc.clj | 7 ++-- test/resources/scripts/test-json-config | 2 +- 5 files changed, 47 insertions(+), 32 deletions(-) create mode 100644 src/degasolv/pkgsys/git.clj diff --git a/project.clj b/project.clj index c9f18ba..a680787 100644 --- a/project.clj +++ b/project.clj @@ -5,20 +5,20 @@ :url "http://www.eclipse.org/legal/epl-v10.html"} :main degasolv.cli :dependencies [ + [cheshire "5.9.0"] + [org.clojure/tools.reader "1.3.2"] [com.velisco/tagged "0.5.0"] [org.clojure/clojure "1.10.1"] - [org.clojure/data.json "0.2.6"] - ;;[org.clojure/spec.alpha "0.2.176"] [org.clojure/tools.cli "0.3.5"] [serovers "1.6.2"] ] :plugins [[lein-licenses "0.2.2"] [lein-print "0.1.0"]] -;; :source-paths ["src/degasolv"] - - :java-source-paths ["src/java" "test/java"] - :junit ["test/java"] + :java-source-paths ["src/java" + "test/java"] + :junit ["test/java"] +;;:source-paths ["src/degasolv"] :global-vars {*warn-on-reflection* true} @@ -43,6 +43,7 @@ degasolv.pkgsys.core degasolv.pkgsys.apt degasolv.pkgsys.subproc + degasolv.pkgsys.git degasolv.util degasolv.resolver degasolv.cli diff --git a/src/degasolv/cli.clj b/src/degasolv/cli.clj index f4e3b6a..3405f32 100644 --- a/src/degasolv/cli.clj +++ b/src/degasolv/cli.clj @@ -1,7 +1,7 @@ (ns degasolv.cli (:require [clojure.pprint :as pprint] - [clojure.data.json :as json] + [cheshire.core :as json] [clojure.edn :as edn] [clojure.set :as st] [clojure.spec.alpha :as s] @@ -9,6 +9,7 @@ [clojure.tools.cli :refer [parse-opts summarize]] [clojure.java.io :as io] [degasolv.pkgsys.apt :as apt-pkg] + [degasolv.pkgsys.git :as git-pkg] [degasolv.pkgsys.core :as degasolv-pkg] [degasolv.pkgsys.subproc :as subproc-pkg] [degasolv.resolver :as r :refer :all] @@ -41,13 +42,13 @@ ^:private version-comparators { - "debian" vers/debian-vercmp - "maven" vers/debian-vercmp - "naive" vers/naive-vercmp - "python" vers/python-vercmp - "rpm" vers/rpm-vercmp + "debian" vers/debian-vercmp + "maven" vers/debian-vercmp + "naive" vers/naive-vercmp + "python" vers/python-vercmp + "rpm" vers/rpm-vercmp "rubygem" vers/rubygem-vercmp - "semver" vers/semver-vercmp + "semver" vers/semver-vercmp }) (defn required-args-msg [required-args & {:keys [sub-command]}] @@ -97,7 +98,9 @@ ^:private package-systems {"apt" {:genrepo apt-pkg/slurp-apt-repo - :version-comparison "debian"} + :version-comparison "debian"} + "git" {:constructor git-pkg/make-slurper + :version-comparison "semver"} "degasolv" {:genrepo degasolv-pkg/slurp-degasolv-repo :version-comparison "semver"} "subproc" {:constructor subproc-pkg/make-slurper @@ -214,9 +217,9 @@ [index-strat repositories genrepo - cmp] + version-comparator] ((aggregator index-strat - cmp) + version-comparator) (flatten (map (fn [url] @@ -234,7 +237,7 @@ }] (case (:output-format options) "json" - (println (json/write-str result-info :escape-slash false)) + (println (json/generate-string result-info)) ;; escape-slash false "edn" (println (pr-str result-info)) "plain" @@ -359,7 +362,7 @@ (println (case output-format "json" - (json/write-str result-info :escape-slash false) + (json/generate-string result-info) "edn" (pr-str result-info) "plain" @@ -374,7 +377,7 @@ (out-exit 3 (case output-format "json" - (json/write-str result-info :escape-slash false) + (json/generate-string result-info) "edn" (pr-str result-info) "plain" @@ -415,10 +418,10 @@ (get version-comparators version-comparison) aggregate-repo (aggregate-repositories - index-strat - repositories - (get-in package-systems [package-system :genrepo]) - version-comparator) + index-strat + repositories + (get-in package-systems [package-system :genrepo]) + version-comparator) req (first (string-to-requirement query)) {:keys [id spec]} req spec-call (make-spec-call @@ -438,7 +441,7 @@ (out-exit 2 (case output-format "json" - (json/write-str result-info :escape-slash false) + (json/generate-string result-info) "edn" (pr-str result-info) "plain" @@ -451,7 +454,7 @@ (println (case output-format "json" - (json/write-str result-info :escape-slash false) + (json/generate-string result-info) "edn" (pr-str result-info) "plain" @@ -524,7 +527,7 @@ (fn [m k v] (update-in m [:config-files] (fn add-cfg [coll] (conj coll {:file v - :read-fn #(json/read-str % :key-fn keyword)}))))] + :read-fn #(json/parse-string % true)}))))] ["-k" "--option-pack PACK" "Specify option pack **" :id :option-packs :default [] @@ -792,7 +795,6 @@ it) (reduce merge it))) - (defn -main [& args] (let [{:keys [options arguments]} (parseplz! "degasolv" args cli-spec)] diff --git a/src/degasolv/pkgsys/git.clj b/src/degasolv/pkgsys/git.clj new file mode 100644 index 0000000..2c0ae91 --- /dev/null +++ b/src/degasolv/pkgsys/git.clj @@ -0,0 +1,13 @@ +(ns degasolv.pkgsys.git + "Namespace containing functions related to the git package system + integration point." + (:require [clojure.string :as string] + [clojure.java.shell :as sh] + [cheshire.core :as json] + [clojure.walk :as walk] + [miner.tagged :as tag] + [degasolv.util :refer :all] + [degasolv.resolver :as r :refer :all])) + +(defn make-slurper [options] + ) diff --git a/src/degasolv/pkgsys/subproc.clj b/src/degasolv/pkgsys/subproc.clj index 05109de..f9b50a1 100644 --- a/src/degasolv/pkgsys/subproc.clj +++ b/src/degasolv/pkgsys/subproc.clj @@ -3,12 +3,11 @@ integration point." (:require [clojure.string :as string] [clojure.java.shell :as sh] - [clojure.data.json :as json] + [cheshire.core :as json] [clojure.walk :as walk] [miner.tagged :as tag] [degasolv.util :refer :all] - [degasolv.resolver :as r :refer :all]) - (:import (java.util.zip GZIPInputStream))) + [degasolv.resolver :as r :refer :all])) (defn convert-input [raw-repo-info] (as-> raw-repo-info it @@ -61,7 +60,7 @@ (let [raw-repo-info (cond (= subproc-output-format "json") - (json/read-str out) + (json/parse-string out) (= subproc-output-format "edn") (tag/read-string out) :else diff --git a/test/resources/scripts/test-json-config b/test/resources/scripts/test-json-config index 426e429..4a41574 100755 --- a/test/resources/scripts/test-json-config +++ b/test/resources/scripts/test-json-config @@ -20,7 +20,7 @@ cd "${test_home}" cat > "degasolv.json" << JSON { - "id": "a", + "id": "a\\\\b", "version": "1.0.0", "location": "https://example.com/repo/a-1.0.0.zip", "requirements": ["c", "d"] From 07084b65542254dbe11e5417fc38a63149b101b9 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Mon, 26 Aug 2019 13:11:55 -0600 Subject: [PATCH 10/41] Spruce up docs --- docs/architecture.rst | 49 ++++++++++++++++++++++++++++++++++++++ docs/command-reference.rst | 5 ++++ docs/index.rst | 1 + 3 files changed, 55 insertions(+) create mode 100644 docs/architecture.rst diff --git a/docs/architecture.rst b/docs/architecture.rst new file mode 100644 index 0000000..ad79ec3 --- /dev/null +++ b/docs/architecture.rst @@ -0,0 +1,49 @@ +.. _Code of Conduct: + +Architecture +============ + +This article describes the overarching architecture of Degasolv, together with +some explanation about some of the design decisions. + +Background +---------- + +At one of my previous jobs, I was a Build Engineer -- a person who built the +code that the developers wrote and made it available. I had *lots* of +dependency problems coming at me from all different sides: + + * One module in language A depending on another from language B + * Developers working with a language (at the time) with no clear package + manager ecosystem (**cough** C++ **cough**) + * Package manager developers breaking builds with backwards-incompatible + behavior + * A dependency graph that looked like a dream catcher + +So I decided to build a tool that would do these things: + + * Resolve dependencies the right way, safely + * Even resolve dependency chains for different package systems (apt, pip, + java) + * Be super versatile and generic, able to be plugged into an arbitrary build + script + +Core Resolver +------------- + +At the core of degasolv is a monster method called `resolve-dependencies`_. It +is a rather large method with a backtracking SAT-solver-ish design. Originally +it was written to have a :ref:`conflict-strat` of ``exclusive`` +and a :ref:`resolve-strat` of ``thorough`` hard-coded. In other +words, the "first class" original use case of degasolv was a SAT-solver-class +depedency resolver that only allowed a single version of any dependency, and +ensured that all parties depending on that dependency had a chance to agree on +what was chosen. These options were later added to allow degasolv to act more +like maven and give any Building Engineer using degasolv useful "handbreaks" to +change how resolution was being done in-house so that it could be modified to +conform to business needs. Other options, such as `list-strat` and +`search-strat` were added as time progressed as well for similar +reasons, and also, frankly, to fix bugs (behaviors that were never originally +intended). + +.. _resolve-dependencies: https://github.com/djhaskin987/degasolv/blob/develop/src/degasolv/resolver_core.clj#L519 diff --git a/docs/command-reference.rst b/docs/command-reference.rst index cba2c1d..d6bc2d3 100644 --- a/docs/command-reference.rst +++ b/docs/command-reference.rst @@ -974,6 +974,8 @@ option on a command line, the last argument of the two specified wins. when debugging a build. If it *is* used routinely, it should be used `site-wide`_. +.. _search-strat: + Specify Solution Search Strategy ******************************** @@ -1504,6 +1506,9 @@ authentication is required to download the index, as in this example:: .. _cURL: https://curl.haxx.se/ + +.. _resolve-strat: + Specify a Resolution Strategy ***************************** diff --git a/docs/index.rst b/docs/index.rst index 38d8103..37ea2a0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -24,6 +24,7 @@ Fork Degasolv on Github: A Longer Example Changelog Command Reference + Architecture Code of Conduct Contributing Guide Roadmap From a01bf7d6c0d9dd5ff4f00110e0d2575297c0acee Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Tue, 27 Aug 2019 11:47:44 -0600 Subject: [PATCH 11/41] Tests pass, more refactoring to come --- project.clj | 6 +- src/degasolv/resolver_core.clj | 244 ++++++++++++++++++++------------- 2 files changed, 150 insertions(+), 100 deletions(-) diff --git a/project.clj b/project.clj index a680787..7c7c224 100644 --- a/project.clj +++ b/project.clj @@ -5,8 +5,12 @@ :url "http://www.eclipse.org/legal/epl-v10.html"} :main degasolv.cli :dependencies [ + ;; optional dependencies to clj-http [cheshire "5.9.0"] - [org.clojure/tools.reader "1.3.2"] + ;;[org.clojure/tools.reader "1.3.2"] + ;;[crouton "0.1.2"] + ;;[ring/ring-codec "1.1.2"] + ;;[ [com.velisco/tagged "0.5.0"] [org.clojure/clojure "1.10.1"] [org.clojure/tools.cli "0.3.5"] diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index e8a936e..ecf898a 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -303,6 +303,42 @@ (let [{:keys [pkg-list visited]} (list-pkgs-rec #{} #{:root} :root)] pkg-list))) +(defn vet-candidate + "Takes a candidate package which has been chosen in hopes of fulfilling a + requirement and ensures that: + 1) It does not violate any 'ensure absent' specifications and + 2) It fulfills the particular 'ensure present' spec." + [absent-specs safe-spec-call id spec candidate] + (and + (safe-spec-call spec candidate) + (reduce + (fn [x y] + (and + x + (not + (safe-spec-call + y + candidate)))) + true + (get absent-specs id)))) + +(defn seek-package + "Seek a package from a repository meeting the specs given." + [safe-spec-call repo absent-specs id spec] + (let [query-results (repo id)] + (if (empty? query-results) + [:unsuccessful + {:problem :empty-query-results}] + (let [filtered-query-results + (filter + (partial vet-candidate absent-specs safe-spec-call id spec) + query-results)] + (if (empty? filtered-query-results) + [:unsuccessful + {:problem :unsatisfactory-query-results}] + [:successful + filtered-query-results]))))) + (defn make-resolve-deps [conflict-strat concat-reqs @@ -384,7 +420,21 @@ (not (nil? present-id-packages))) (not (= conflict-strat :inclusive))) [:unsuccessful - {:problems + {:suggestions + ;; pass suggestions up the chain + (when (and + (nil? present-id-packages) + (not (nil? found-id-packages))) + (when-let [[status pkgs] + (first-successful + (seek-package + safe-spec-call + repo + absent-specs + id + spec))] + {id pkgs})) + :problems [ {:term clause :found-packages found-packages @@ -407,37 +457,72 @@ rclauses package-graph) (= status :present) - (let [query-results (repo id)] - (if (empty? query-results) - [:unsuccessful - {:problems - [ - {:term clause - :alternative alternative - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs - :reason :package-not-found - :package-id id}]}] + (let [[status query-response] + (seek-package + safe-spec-call + repo + absent-specs + id + spec)] + (if (= status :successful) (let [filtered-query-results - (cull - (filter - (fn vet-candidate - [candidate] - (and - (safe-spec-call spec candidate) - (reduce - (fn [x y] - (and - x - (not - (safe-spec-call - y - candidate)))) - true - (get absent-specs id)))) - query-results))] - (if (empty? filtered-query-results) + (cull query-response) + candidate-results + (first-found + (fn + try-candidate + [candidate] + (resolve-deps + repo + present-packages + (update-in found-packages + [id] + #(if (empty? %1) + (do [%2]) + (conj %1 %2)) + candidate) + absent-specs + (concat-reqs + rclauses + (map + #(->DecoratedRequirement + % + candidate) + (:requirements + candidate))) + (update-in package-graph + [parent] + #(if (empty? %1) + (do [%2]) + (conj %1 %2)) + candidate))) + successful? + filtered-query-results)] + (or + (some + first-successful + candidate-results) + [:unsuccessful + {:problems + (flatten + (map + #(:problems + (get % 1)) + candidate-results))}])) + (let [{problem :problem} query-response] + (cond + (= problem :empty-query-results) + [:unsuccessful + {:problems + [ + {:term clause + :alternative alternative + :found-packages found-packages + :present-packages present-packages + :absent-specs absent-specs + :reason :package-not-found + :package-id id}]}] + (= problem :unsatisfactory-query-results) [:unsuccessful {:problems [{:term clause @@ -447,74 +532,35 @@ :absent-specs absent-specs :reason :package-rejected :package-id id}]}] - (let [candidate-results - (first-found - (fn - try-candidate - [candidate] - (resolve-deps - repo - present-packages - (update-in found-packages - [id] - #(if (empty? %1) - (do [%2]) - (conj %1 %2)) - candidate) - absent-specs - (concat-reqs - rclauses - (map - #(->DecoratedRequirement - % - candidate) - (:requirements - candidate))) - (update-in package-graph - [parent] - #(if (empty? %1) - (do [%2]) - (conj %1 %2)) - candidate))) - successful? - filtered-query-results)] - (or - (some - first-successful - candidate-results) - [:unsuccessful - {:problems - (flatten - (map - #(:problems - (get % 1)) - candidate-results))}])))))) - :else - [:unsuccessful {:problems - [{:term clause - :reason :uncovered-case - :alternative alternative - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs}]}]))) - successful? - ;; Hoisting - (hoist (cull-alternatives - clause) - absent-specs - found-packages - present-packages))] - (or - (some - first-successful - clause-result) - [:unsuccessful - {:problems - (flatten - (map - #(:problems - (get % 1)) - clause-result))}]))))))) + :else + [:unsuccessful + {:problems + [{:term clause + :alternative alternative + :found-packages found-packages + :present-packages present-packages + :absent-specs absent-specs + :reason :seek-package-logic-error + :package-id id}]}])) + ))))) +successful? +;; Hoisting +(hoist (cull-alternatives + clause) + absent-specs + found-packages + present-packages))] +(or + (some + first-successful + clause-result) + [:unsuccessful + {:problems + (flatten + (map + #(:problems + (get % 1)) + clause-result))}]))))))) (defn resolve-dependencies [requirements From 9ffba7f307144638c761b19a3dd5214406167e8c Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Tue, 27 Aug 2019 13:30:02 -0600 Subject: [PATCH 12/41] Moar refactoring --- src/degasolv/resolver_core.clj | 57 ++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index ecf898a..f4135cf 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -209,19 +209,19 @@ result))) ;; If transformed value passes test, -;; return a singleton list of those; -;; otherwise, return the full list of transformed stuffs. +;; return the it; otherwise, return an aggregated version of the +;; values that don't pass the test. ;; This is because lazy seqs in clojure aren't exactly lazy; ;; they're "chunked" lazy, which is sad. Sad panda :'( (defn- first-found - [f pred coll] + [f aggregate pred coll] (reduce (fn find-first [c v] (let [new-v (f v)] (if (pred new-v) (reduced [new-v]) - (conj c new-v)))) + (aggregate c new-v)))) [] coll)) @@ -339,6 +339,21 @@ [:successful filtered-query-results]))))) +(defn make-error + [present-packages found-packages absent-specs clause reason & + {:keys [] :as additional}] + (let [base-problem + {:term clause + :found-packages found-packages + :present-packages present-packages + :absent-specs absent-specs + :reason reason} + problem + (into base-problem additional)] + [:unsuccessful + {:problems + [problem]}])) + (defn make-resolve-deps [conflict-strat concat-reqs @@ -358,15 +373,14 @@ (let [fclause (first clauses) rclauses (rest clauses) {:keys [clause parent]} - fclause] + fclause + mkerror (partial make-error + present-packages + found-packages + absent-specs + clause)] (if (empty? clause) - [:unsuccessful - {:problems - [{:term clause - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs - :reason :empty-alternative-set}]}] + (mkerror :empty-alternative-set) (let [clause-result (first-found (fn try-alternative @@ -419,8 +433,10 @@ (not (nil? found-id-packages)) (not (nil? present-id-packages))) (not (= conflict-strat :inclusive))) - [:unsuccessful - {:suggestions + (mkerror + :present-package-conflict + :alternative alternative + :suggestions ;; pass suggestions up the chain (when (and (nil? present-id-packages) @@ -433,16 +449,7 @@ absent-specs id spec))] - {id pkgs})) - :problems - [ - {:term clause - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs - :reason :present-package-conflict - :alternative alternative - :package-id id}]}] + {id pkgs}))) (= status :absent) (resolve-deps repo @@ -496,6 +503,7 @@ (do [%2]) (conj %1 %2)) candidate))) + conj successful? filtered-query-results)] (or @@ -543,6 +551,7 @@ :reason :seek-package-logic-error :package-id id}]}])) ))))) +conj successful? ;; Hoisting (hoist (cull-alternatives From 6be817b2a9695b71b24d4616fdd61e19eab45146 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Tue, 27 Aug 2019 13:35:42 -0600 Subject: [PATCH 13/41] Make full use of make-error --- src/degasolv/resolver_core.clj | 38 +++++++--------------------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index f4135cf..c780580 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -517,40 +517,18 @@ #(:problems (get % 1)) candidate-results))}])) - (let [{problem :problem} query-response] + (let [{problem :problem} query-response + pkg-error (fn [reason] + (mkerror reason + :alternative alternative + :package-id id))] (cond (= problem :empty-query-results) - [:unsuccessful - {:problems - [ - {:term clause - :alternative alternative - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs - :reason :package-not-found - :package-id id}]}] + (pkg-error :package-not-found) (= problem :unsatisfactory-query-results) - [:unsuccessful - {:problems - [{:term clause - :alternative alternative - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs - :reason :package-rejected - :package-id id}]}] + (pkg-error :package-rejected) :else - [:unsuccessful - {:problems - [{:term clause - :alternative alternative - :found-packages found-packages - :present-packages present-packages - :absent-specs absent-specs - :reason :seek-package-logic-error - :package-id id}]}])) - ))))) + (pkg-error :seek-package-logic-error)))))))) conj successful? ;; Hoisting From f1c6c4b833435b13f22e95ac1c0fd9efb434814b Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 28 Aug 2019 12:30:01 -0600 Subject: [PATCH 14/41] Update documentation --- docs/changelog.rst | 9 ++++++++- docs/roadmap.rst | 21 +++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 355fdb7..4f76c85 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -17,10 +17,17 @@ and this project adheres to `Semantic Versioning`_. Added +++++ +- If the reason for failure in the ``resolve-dependencies`` function + is ``:present-package-conflict``, add a key ``:package-present-by`` with + value as either ``:found`` meaning the package was in conflict with a package + found during resolution, or with value as ``:given`` meaning the package + was in conflict with a package given via the parameter ``present-packages``. + Changed +++++++ -- Removed the deprecated functions ``->requirement``, ``->package``, and ``->version-predicate`` from usage in the code base. +- Removed the deprecated functions ``->requirement``, ``->package``, and + ``->version-predicate`` from usage in the code base. Fixed +++++ diff --git a/docs/roadmap.rst b/docs/roadmap.rst index f82b7e7..a196ba9 100644 --- a/docs/roadmap.rst +++ b/docs/roadmap.rst @@ -8,13 +8,26 @@ after all. Nevertheless, for what it's worth, here is the current roadmap. 2.1.0 ----- + - **Catch and release**: Catch failed clause resolutions early when the failed clause's package name in a recursive call matches the present clause. This should significantly speed up clause resolution and make the idea of minimum - version selection possible. -- **Minimum Version Selection**: Implement minimum version selection by - introducing an option into resolve-locations that instructs degasolv which to - choose: the smallest version available or the largest. + version selection possible. Supporting features: + +- **Minimum Version Selection**: Implement minimum version selection as an + option pack. Supporting features: + - Version suggestion: when trying different candidates, if a matching id is + in the return of a candidate, put the suggestions in the list to loop + through. + - Skip unlikely candidates: Keep a set of problem ids different candidates + are tried. If the current alternative's ID is not in that set, and if the + dependencies are the same as the previous candidate, then skip the + candidate; do not try it. + - Minimum version preference: In generate repo index, add option to sort + packages the other way. + - Proper documentation surrounding order of encounter, that for example for + subproc degasolv will honor the order of packages found in the repo index + and that this enables things like MVS. Future Features --------------- From 654ace329b23eeaf38fe27205d33cfa20ccc5e83 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 28 Aug 2019 13:26:05 -0600 Subject: [PATCH 15/41] Code complete with version suggestion. I think. --- project.clj | 2 + src/degasolv/resolver.clj | 4 +- src/degasolv/resolver_core.clj | 125 +++++++++++++++++++++++---------- 3 files changed, 91 insertions(+), 40 deletions(-) diff --git a/project.clj b/project.clj index 7c7c224..fe212e6 100644 --- a/project.clj +++ b/project.clj @@ -5,6 +5,8 @@ :url "http://www.eclipse.org/legal/epl-v10.html"} :main degasolv.cli :dependencies [ + ;; ordered set for version suggestion + [org.flatland/ordered "1.5.7"] ;; optional dependencies to clj-http [cheshire "5.9.0"] ;;[org.clojure/tools.reader "1.3.2"] diff --git a/src/degasolv/resolver.clj b/src/degasolv/resolver.clj index 1ca94e7..0abdce7 100644 --- a/src/degasolv/resolver.clj +++ b/src/degasolv/resolver.clj @@ -1,9 +1,11 @@ (ns degasolv.resolver "Namespace containing `resolve-dependencies` and supporting functions." (:require [degasolv.util :refer :all] + [clojure.set :as set] [clojure.spec.alpha :as s] [clojure.string :as clj-str] - [miner.tagged :as tag])) + [miner.tagged :as tag] + [flatland.ordered.set :as memset])) (defmacro dbg [body] `(let [x# ~body] diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index c780580..6864c50 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -308,7 +308,7 @@ requirement and ensures that: 1) It does not violate any 'ensure absent' specifications and 2) It fulfills the particular 'ensure present' spec." - [absent-specs safe-spec-call id spec candidate] + [id-absent-specs safe-spec-call spec candidate] (and (safe-spec-call spec candidate) (reduce @@ -320,18 +320,18 @@ y candidate)))) true - (get absent-specs id)))) + id-absent-specs))) (defn seek-package "Seek a package from a repository meeting the specs given." - [safe-spec-call repo absent-specs id spec] + [repo vet] (let [query-results (repo id)] (if (empty? query-results) [:unsuccessful {:problem :empty-query-results}] (let [filtered-query-results (filter - (partial vet-candidate absent-specs safe-spec-call id spec) + vet query-results)] (if (empty? filtered-query-results) [:unsuccessful @@ -354,6 +354,55 @@ {:problems [problem]}])) + +(defn merge-failure-records + "Merge two different resolution failure records. + Merge using ``(merge-with into ...)`` for everything but suggestions; + within the suggestions, merge using ``(merge-with set/intersection ...)``." + [a b] + (let [(merge-with into (dissoc a :suggestions) + (dissoc b :suggestions)) base-answer] + (if-let [a-suggestions (:suggestions a)] + (if-let [b-suggestions (:suggestions b)] + (assoc + base-answer + :suggestions + (merge-with set/intersection + a-suggestions + b-suggestions)) + (assoc + base-answer + :suggestions + a-suggestions)) + (if-let [b-suggestions (:suggestions b)] + (assoc + base-answer + :suggestions + b-suggestions)) + base-answer))) + +(defn try-candidates + [vet + try-candidate + candidates] + (loop [remaining + failure-record] + (if (empty? remaining) + [:unsuccessful + failure-record] + (let [falt (first remaining) + ralt (rest remaining) + [status result :as response] (try-candidate falt)] + (if (successful? response) + response + (recur + (if-let [suggestions (:suggestions result)] + (into (filter vet suggestions) + ralt) + ralt) + (merge-with merge-failure-records failure-record base-failure-record))))))) + + (defn make-resolve-deps [conflict-strat concat-reqs @@ -387,6 +436,11 @@ [alternative] (let [{status :status id :id spec :spec} alternative + vet + (partial vet-candidate + (get absent-specs id) + safe-spec-call + spec) present-id-packages (get present-packages id) found-id-packages @@ -429,27 +483,33 @@ (do [%2]) (conj %1 %2)) found-package)) - (and (or - (not (nil? found-id-packages)) - (not (nil? present-id-packages))) - (not (= conflict-strat :inclusive))) + + (and + (not (= conflict-strat :inclusive)) + (not (nil? present-id-packages))) (mkerror :present-package-conflict :alternative alternative - :suggestions - ;; pass suggestions up the chain - (when (and - (nil? present-id-packages) - (not (nil? found-id-packages))) - (when-let [[status pkgs] - (first-successful - (seek-package - safe-spec-call - repo - absent-specs - id - spec))] - {id pkgs}))) + :package-present-by :given) + (and + (not (= conflict-strat :inclusive)) + (not (nil? found-id-packages))) + (if-let [[status pkgs] + (first-successful + (seek-package + repo + vet))] + (mkerror + :present-package-conflict + :alternative alternative + ;; pass suggestions up the chain + :suggestions + {id (memset/ordered-set pkgs)} + :package-present-by :found) + (mkerror + :present-package-conflict + :alternative alternative + :package-present-by :found)) (= status :absent) (resolve-deps repo @@ -473,9 +533,8 @@ spec)] (if (= status :successful) (let [filtered-query-results - (cull query-response) - candidate-results - (first-found + (cull query-response)] + (try-candidates (fn try-candidate [candidate] @@ -503,20 +562,8 @@ (do [%2]) (conj %1 %2)) candidate))) - conj - successful? - filtered-query-results)] - (or - (some - first-successful - candidate-results) - [:unsuccessful - {:problems - (flatten - (map - #(:problems - (get % 1)) - candidate-results))}])) + vet + filtered-query-results)) (let [{problem :problem} query-response pkg-error (fn [reason] (mkerror reason From d3e0d49c4f84717038a2f12800a2384e847af47b Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 28 Aug 2019 13:58:49 -0600 Subject: [PATCH 16/41] No errors, but a test doesn't pass with version suggestion --- docs/changelog.rst | 2 ++ project.clj | 5 +++- src/degasolv/resolver_core.clj | 50 ++++++++++++++-------------------- 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 4f76c85..66201d1 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -29,6 +29,8 @@ Changed - Removed the deprecated functions ``->requirement``, ``->package``, and ``->version-predicate`` from usage in the code base. +- Removed ``dbg2`` macro in favor of keeping ``dbg`` + Fixed +++++ diff --git a/project.clj b/project.clj index fe212e6..6039aa4 100644 --- a/project.clj +++ b/project.clj @@ -35,12 +35,15 @@ :profiles { :dev { :dependencies [ + ;; ordered set for version suggestion + [org.flatland/ordered "1.5.7"] [org.clojure/core.match "0.3.0-alpha5"] [org.clojure/clojure "1.10.1"] [serovers "1.6.2"] [org.clojure/tools.cli "0.3.5"] [com.velisco/tagged "0.5.0"] - [org.clojure/data.json "0.2.6"] + ;; optional dependencies to clj-http + [cheshire "5.9.0"] ] :plugins [[test2junit "1.3.3"]] :test2junit-output-dir "target/test-results" diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index 6864c50..6fa6b19 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -1,10 +1,5 @@ (in-ns 'degasolv.resolver) -(defmacro dbg2 [body] - `(let [x# ~body] - (println "dbg:" '~body "=" x#) - x#)) - (def ^:private relation-strings {:greater-than ">" :greater-equal ">=" @@ -324,8 +319,7 @@ (defn seek-package "Seek a package from a repository meeting the specs given." - [repo vet] - (let [query-results (repo id)] + [query-results vet] (if (empty? query-results) [:unsuccessful {:problem :empty-query-results}] @@ -337,7 +331,7 @@ [:unsuccessful {:problem :unsatisfactory-query-results}] [:successful - filtered-query-results]))))) + filtered-query-results])))) (defn make-error [present-packages found-packages absent-specs clause reason & @@ -360,8 +354,10 @@ Merge using ``(merge-with into ...)`` for everything but suggestions; within the suggestions, merge using ``(merge-with set/intersection ...)``." [a b] - (let [(merge-with into (dissoc a :suggestions) - (dissoc b :suggestions)) base-answer] + (let [base-answer (merge-with + into + (dissoc a :suggestions) + (dissoc b :suggestions))] (if-let [a-suggestions (:suggestions a)] (if-let [b-suggestions (:suggestions b)] (assoc @@ -378,15 +374,15 @@ (assoc base-answer :suggestions - b-suggestions)) - base-answer))) + b-suggestions) + base-answer)))) (defn try-candidates - [vet - try-candidate + [try-candidate + vet candidates] - (loop [remaining - failure-record] + (loop [remaining candidates + failure-record {}] (if (empty? remaining) [:unsuccessful failure-record] @@ -395,13 +391,12 @@ [status result :as response] (try-candidate falt)] (if (successful? response) response - (recur - (if-let [suggestions (:suggestions result)] - (into (filter vet suggestions) - ralt) - ralt) - (merge-with merge-failure-records failure-record base-failure-record))))))) - + (recur + (if-let [suggestions (:suggestions result)] + (into (filter vet suggestions) + ralt) + ralt) + (merge-failure-records failure-record result))))))) (defn make-resolve-deps [conflict-strat @@ -497,7 +492,7 @@ (if-let [[status pkgs] (first-successful (seek-package - repo + (repo id) vet))] (mkerror :present-package-conflict @@ -526,11 +521,8 @@ (= status :present) (let [[status query-response] (seek-package - safe-spec-call - repo - absent-specs - id - spec)] + (repo id) + vet)] (if (= status :successful) (let [filtered-query-results (cull query-response)] From 3b2b922a013d378389b4f0b79f66c29b4d806af4 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 28 Aug 2019 14:29:01 -0600 Subject: [PATCH 17/41] Tests pass for version suggestion, but need to actually add a version suggestion test --- project.clj | 117 ++++++++++--------- test/degasolv/resolver/unsuccessful_test.clj | 4 +- 2 files changed, 62 insertions(+), 59 deletions(-) diff --git a/project.clj b/project.clj index 6039aa4..68c5760 100644 --- a/project.clj +++ b/project.clj @@ -1,62 +1,65 @@ (defproject degasolv/degasolv "2.1.0-SNAPSHOT" - :description "Dependency tracker with an eye toward building and shipping software." - :url "http://github.com/djhaskin987/degasolv" - :license {:name "Eclipse Public License" - :url "http://www.eclipse.org/legal/epl-v10.html"} - :main degasolv.cli - :dependencies [ - ;; ordered set for version suggestion - [org.flatland/ordered "1.5.7"] - ;; optional dependencies to clj-http - [cheshire "5.9.0"] - ;;[org.clojure/tools.reader "1.3.2"] - ;;[crouton "0.1.2"] - ;;[ring/ring-codec "1.1.2"] - ;;[ - [com.velisco/tagged "0.5.0"] - [org.clojure/clojure "1.10.1"] - [org.clojure/tools.cli "0.3.5"] - [serovers "1.6.2"] - ] - :plugins [[lein-licenses "0.2.2"] - [lein-print "0.1.0"]] + :description "Dependency tracker with an eye toward building and shipping software." + :url "http://github.com/djhaskin987/degasolv" + :license {:name "Eclipse Public License" + :url "http://www.eclipse.org/legal/epl-v10.html"} + :main degasolv.cli + :dependencies [ + ;; ordered set for version suggestion + [org.flatland/ordered "1.5.7"] + ;; optional dependencies to clj-http + [cheshire "5.9.0"] + ;;[org.clojure/tools.reader "1.3.2"] + ;;[crouton "0.1.2"] + ;;[ring/ring-codec "1.1.2"] + ;;[ + [com.velisco/tagged "0.5.0"] + [org.clojure/clojure "1.10.1"] + [org.clojure/tools.cli "0.3.5"] + [serovers "1.6.2"] + ] + :plugins [[lein-licenses "0.2.2"] + [lein-print "0.1.0"]] - :java-source-paths ["src/java" - "test/java"] - :junit ["test/java"] -;;:source-paths ["src/degasolv"] + :java-source-paths ["src/java" + "test/java"] + :junit ["test/java"] + ;;:source-paths ["src/degasolv"] - :global-vars {*warn-on-reflection* true} + :global-vars {*warn-on-reflection* true} - :test-selectors - { - :unit-tests :unit-tests - } - :profiles { - :dev { - :dependencies [ - ;; ordered set for version suggestion - [org.flatland/ordered "1.5.7"] - [org.clojure/core.match "0.3.0-alpha5"] - [org.clojure/clojure "1.10.1"] - [serovers "1.6.2"] - [org.clojure/tools.cli "0.3.5"] - [com.velisco/tagged "0.5.0"] - ;; optional dependencies to clj-http - [cheshire "5.9.0"] - ] - :plugins [[test2junit "1.3.3"]] - :test2junit-output-dir "target/test-results" - } - :uberjar {:aot [ - degasolv.pkgsys.core - degasolv.pkgsys.apt - degasolv.pkgsys.subproc - degasolv.pkgsys.git - degasolv.util - degasolv.resolver - degasolv.cli - ]} + :test-selectors + { + :unit-tests :unit-tests } - :target-path "target/%s/" - ) + :profiles { + :dev { + :dependencies [ + [pjstadig/humane-test-output "0.9.0"] + ;; ordered set for version suggestion + [org.flatland/ordered "1.5.7"] + [org.clojure/core.match "0.3.0-alpha5"] + [org.clojure/clojure "1.10.1"] + [serovers "1.6.2"] + [org.clojure/tools.cli "0.3.5"] + [com.velisco/tagged "0.5.0"] + ;; optional dependencies to clj-http + [cheshire "5.9.0"] + ] + :plugins [[test2junit "1.3.3"]] + :test2junit-output-dir "target/test-results" + :injections [(require 'pjstadig.humane-test-output) + (pjstadig.humane-test-output/activate!)] + } + :uberjar {:aot [ + degasolv.pkgsys.core + degasolv.pkgsys.apt + degasolv.pkgsys.subproc + degasolv.pkgsys.git + degasolv.util + degasolv.resolver + degasolv.cli + ]} + } + :target-path "target/%s/" + ) diff --git a/test/degasolv/resolver/unsuccessful_test.clj b/test/degasolv/resolver/unsuccessful_test.clj index f4f9df3..d9ed4f0 100644 --- a/test/degasolv/resolver/unsuccessful_test.clj +++ b/test/degasolv/resolver/unsuccessful_test.clj @@ -180,7 +180,7 @@ :found-packages {"a" [a2] "b" - [b2]} + [b3]} :present-packages {} :absent-specs {} :reason :package-not-found @@ -190,7 +190,7 @@ :found-packages {"a" [a2] "b" - [b3]} + [b2]} :present-packages {} :absent-specs {} :reason :package-not-found From 132e1afa550094d3decf74c712302493a373668f Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 28 Aug 2019 14:31:14 -0600 Subject: [PATCH 18/41] Update roadmap --- docs/roadmap.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/roadmap.rst b/docs/roadmap.rst index a196ba9..c5db3c1 100644 --- a/docs/roadmap.rst +++ b/docs/roadmap.rst @@ -9,11 +9,6 @@ after all. Nevertheless, for what it's worth, here is the current roadmap. 2.1.0 ----- -- **Catch and release**: Catch failed clause resolutions early when the failed - clause's package name in a recursive call matches the present clause. This - should significantly speed up clause resolution and make the idea of minimum - version selection possible. Supporting features: - - **Minimum Version Selection**: Implement minimum version selection as an option pack. Supporting features: - Version suggestion: when trying different candidates, if a matching id is @@ -29,6 +24,10 @@ after all. Nevertheless, for what it's worth, here is the current roadmap. subproc degasolv will honor the order of packages found in the repo index and that this enables things like MVS. +- **Git package system**: Implement git package system that knows how to + read bitbucket, bitbucket server, github, github server, gitlab, gitlab + server, and raw git repos. + Future Features --------------- - **Compile with GraalVM's ``native-image``**: Compile degasolv to machine From 839d360d0099a3ab7a4a07e9c482a10c1a3f3212 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 28 Aug 2019 14:36:38 -0600 Subject: [PATCH 19/41] Fix a bug --- src/degasolv/resolver_core.clj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index 6fa6b19..0a2a707 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -363,9 +363,9 @@ (assoc base-answer :suggestions - (merge-with set/intersection - a-suggestions - b-suggestions)) + (set/intersection + a-suggestions + b-suggestions)) (assoc base-answer :suggestions From 853947169b24b99d23d5ed50376476cb2f54c9c7 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 28 Aug 2019 22:45:58 -0600 Subject: [PATCH 20/41] Add test for version suggestion in unit tests --- src/degasolv/resolver_core.clj | 11 +-- .../degasolv/resolver/version_suggestions.clj | 77 +++++++++++++++++++ 2 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 test/degasolv/resolver/version_suggestions.clj diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index 0a2a707..4d38186 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -386,16 +386,17 @@ (if (empty? remaining) [:unsuccessful failure-record] - (let [falt (first remaining) - ralt (rest remaining) - [status result :as response] (try-candidate falt)] + (let [fcand (first remaining) + rcand (rest remaining) + [status result :as response] (try-candidate fcand)] + (dbg fcand) (if (successful? response) response (recur (if-let [suggestions (:suggestions result)] (into (filter vet suggestions) - ralt) - ralt) + rcand) + rcand) (merge-failure-records failure-record result))))))) (defn make-resolve-deps diff --git a/test/degasolv/resolver/version_suggestions.clj b/test/degasolv/resolver/version_suggestions.clj new file mode 100644 index 0000000..2618334 --- /dev/null +++ b/test/degasolv/resolver/version_suggestions.clj @@ -0,0 +1,77 @@ +(ns degasolv.resolver.version-suggestions + (:require [clojure.test :refer :all] + [degasolv.resolver :refer :all])) + +(deftest + ^:unit-tests minimum-version-selection-case + (let [a + { + :id "a" + :version 10 + :location "http://example.com/repo/a-1.0.0.zip" + :requirements [ + [(present "c" #(>= (:version %) 10))] + [(present "b")] + ] + } + b + { + :id "b" + :version 10 + :location "http://example.com/repo/b-1.0.0.zip" + :requirements [ + [(present "c" #(>= (:version %) 30))] + ] + + } + c10 + { + :id "c" + :version 10 + :location "http://example.com/repo/c-1.0.0.zip" + } + c20 + { + :id "c" + :version 20 + :location "http://example.com/repo/c-2.0.0.zip" + :requirements [[(present "d" #(do (print "foo") (throw (ex-info + "This bomb is intentional. Any attempt to resolve this candidate should cause an error." + {:value %}))))]] + } + c30 + { + :id "c" + :version 30 + :location "http://example.com/repo/c-3.0.0.zip" + } + c40 + { + :id "c" + :version 40 + :location "http://example.com/repo/c-4.0.0.zip" + } + d + { + :id "d" + :version 10 + :location "http://example.com/repo/d-1.0.0.zip" + } + repo-info-asc {"a" [a] + "b" [b] + "c" [c10 c20 c30 c40] + "d" [d]} + query-asc (map-query repo-info-asc)] + (deftest + ^:unit-tests + ^:minimum-version-selection + ^:version-suggestion + mvs + (testing + "Make sure that the bomb version (c20) is skipped." + (is (.equals [:successful #{a b c30}] + (resolve-dependencies + [ + [(present "a")] + ] + query-asc))))))) From 24d1719fdd4042324c0f4cd1ef827dab14a6c692 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Thu, 29 Aug 2019 00:00:11 -0600 Subject: [PATCH 21/41] still debugging, pardon my dust --- src/degasolv/resolver.clj | 1 + src/degasolv/resolver_core.clj | 67 ++++++++++++------- .../degasolv/resolver/version_suggestions.clj | 4 +- 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/degasolv/resolver.clj b/src/degasolv/resolver.clj index 0abdce7..5631012 100644 --- a/src/degasolv/resolver.clj +++ b/src/degasolv/resolver.clj @@ -10,6 +10,7 @@ (defmacro dbg [body] `(let [x# ~body] (println "dbg:" '~body "=" x#) + (flush) x#)) (load "resolver_core") diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index 4d38186..92430b5 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -335,7 +335,9 @@ (defn make-error [present-packages found-packages absent-specs clause reason & - {:keys [] :as additional}] + {:keys [suggestions additional] :or {suggestions {} + additional {}}}] + (dbg suggestions) (let [base-problem {:term clause :found-packages found-packages @@ -345,8 +347,14 @@ problem (into base-problem additional)] [:unsuccessful - {:problems - [problem]}])) + (if (empty? suggestions) + {:problems + [problem]} + {:problems + [problem] + :suggestions + suggestions})])) + (defn merge-failure-records @@ -354,6 +362,9 @@ Merge using ``(merge-with into ...)`` for everything but suggestions; within the suggestions, merge using ``(merge-with set/intersection ...)``." [a b] + (println "merge-failure-records") + (dbg a) + (dbg b) (let [base-answer (merge-with into (dissoc a :suggestions) @@ -390,14 +401,17 @@ rcand (rest remaining) [status result :as response] (try-candidate fcand)] (dbg fcand) + (dbg rcand) (if (successful? response) response (recur - (if-let [suggestions (:suggestions result)] - (into (filter vet suggestions) - rcand) + (if-let [suggestions (:suggestions (dbg result))] + (do + (print "WHAT") + (dbg (into (set/select vet suggestions) + rcand))) rcand) - (merge-failure-records failure-record result))))))) + (dbg (merge-failure-records failure-record result)))))))) (defn make-resolve-deps [conflict-strat @@ -455,6 +469,7 @@ (get-pkg-exists present-id-packages) found-package (get-pkg-exists found-id-packages)] + (dbg id) (cond (not (nil? present-package)) @@ -485,27 +500,32 @@ (not (nil? present-id-packages))) (mkerror :present-package-conflict - :alternative alternative - :package-present-by :given) + :additional + {:alternative alternative + :package-present-by :given}) (and (not (= conflict-strat :inclusive)) (not (nil? found-id-packages))) - (if-let [[status pkgs] + (dbg (if-let [[status pkgs] (first-successful (seek-package (repo id) vet))] (mkerror :present-package-conflict - :alternative alternative + :additional + {:alternative alternative + :package-present-by :found + :suggestion-attempt :successful} ;; pass suggestions up the chain :suggestions - {id (memset/ordered-set pkgs)} - :package-present-by :found) + {id (into (memset/ordered-set) pkgs)}) (mkerror :present-package-conflict - :alternative alternative - :package-present-by :found)) + :additional + {:alternative alternative + :package-present-by :found + :suggestion-attempt :unsuccessful }))) (= status :absent) (resolve-deps repo @@ -560,8 +580,9 @@ (let [{problem :problem} query-response pkg-error (fn [reason] (mkerror reason - :alternative alternative - :package-id id))] + :additional + {:alternative alternative + :package-id id}))] (cond (= problem :empty-query-results) (pkg-error :package-not-found) @@ -582,12 +603,12 @@ successful? first-successful clause-result) [:unsuccessful - {:problems - (flatten - (map - #(:problems - (get % 1)) - clause-result))}]))))))) + (reduce + merge-failure-records + {} + (map + #(get % 1) + clause-result))]))))))) (defn resolve-dependencies [requirements diff --git a/test/degasolv/resolver/version_suggestions.clj b/test/degasolv/resolver/version_suggestions.clj index 2618334..7100f19 100644 --- a/test/degasolv/resolver/version_suggestions.clj +++ b/test/degasolv/resolver/version_suggestions.clj @@ -70,8 +70,8 @@ (testing "Make sure that the bomb version (c20) is skipped." (is (.equals [:successful #{a b c30}] - (resolve-dependencies + (dbg (resolve-dependencies [ [(present "a")] ] - query-asc))))))) + query-asc)))))))) From da1f50c47bf40382273f802300bd55652f18a2c5 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Thu, 29 Aug 2019 00:44:28 -0600 Subject: [PATCH 22/41] Add to roadmap --- docs/roadmap.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/roadmap.rst b/docs/roadmap.rst index c5db3c1..fdd4074 100644 --- a/docs/roadmap.rst +++ b/docs/roadmap.rst @@ -28,6 +28,14 @@ after all. Nevertheless, for what it's worth, here is the current roadmap. read bitbucket, bitbucket server, github, github server, gitlab, gitlab server, and raw git repos. +- **Inclusive/Absent corner case**: In the case that ``conflict-strat`` is + inclusive, a case may arise where an absence is required, but then another + requirement asks for the same package to be present at a conflicting version. + basically, what do requirements of absence mean within and inclusive context. + because right now when absence requirements are given, they hold force even + in inclusive contexts. This seems silly. Requirements of absence should just + be ignored when ``conflict-strat`` is ``inclusive``. + Future Features --------------- - **Compile with GraalVM's ``native-image``**: Compile degasolv to machine From 32dc59f4bc9aca1d758d6787d76052e70623dc96 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Thu, 29 Aug 2019 08:34:07 -0600 Subject: [PATCH 23/41] Add to roadmap --- docs/roadmap.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/roadmap.rst b/docs/roadmap.rst index fdd4074..b080f58 100644 --- a/docs/roadmap.rst +++ b/docs/roadmap.rst @@ -36,6 +36,8 @@ after all. Nevertheless, for what it's worth, here is the current roadmap. in inclusive contexts. This seems silly. Requirements of absence should just be ignored when ``conflict-strat`` is ``inclusive``. +- Fix #17, it is awful. + Future Features --------------- - **Compile with GraalVM's ``native-image``**: Compile degasolv to machine From dddbd5e1793eb9c7259a7da2ffdd6c06741f80f4 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Thu, 29 Aug 2019 14:28:02 -0600 Subject: [PATCH 24/41] Now I'm tracking down some infinite loop. Fortunate --- src/degasolv/resolver_core.clj | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index 92430b5..df23415 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -337,7 +337,6 @@ [present-packages found-packages absent-specs clause reason & {:keys [suggestions additional] :or {suggestions {} additional {}}}] - (dbg suggestions) (let [base-problem {:term clause :found-packages found-packages @@ -362,9 +361,6 @@ Merge using ``(merge-with into ...)`` for everything but suggestions; within the suggestions, merge using ``(merge-with set/intersection ...)``." [a b] - (println "merge-failure-records") - (dbg a) - (dbg b) (let [base-answer (merge-with into (dissoc a :suggestions) @@ -374,9 +370,9 @@ (assoc base-answer :suggestions - (set/intersection - a-suggestions - b-suggestions)) + (merge-with set/intersection + a-suggestions + b-suggestions)) (assoc base-answer :suggestions @@ -394,24 +390,24 @@ candidates] (loop [remaining candidates failure-record {}] + (dbg remaining) (if (empty? remaining) [:unsuccessful failure-record] (let [fcand (first remaining) rcand (rest remaining) + id (:id fcand) [status result :as response] (try-candidate fcand)] - (dbg fcand) - (dbg rcand) (if (successful? response) response (recur - (if-let [suggestions (:suggestions (dbg result))] - (do - (print "WHAT") - (dbg (into (set/select vet suggestions) - rcand))) - rcand) - (dbg (merge-failure-records failure-record result)))))))) + (if-let [relevant-suggestions + (get (:suggestions result) id)] + (into (set/select vet relevant-suggestions) + rcand) + + rcand) + (merge-failure-records failure-record result))))))) (defn make-resolve-deps [conflict-strat @@ -469,7 +465,6 @@ (get-pkg-exists present-id-packages) found-package (get-pkg-exists found-id-packages)] - (dbg id) (cond (not (nil? present-package)) @@ -506,7 +501,7 @@ (and (not (= conflict-strat :inclusive)) (not (nil? found-id-packages))) - (dbg (if-let [[status pkgs] + (if-let [[status pkgs] (first-successful (seek-package (repo id) @@ -525,7 +520,7 @@ :additional {:alternative alternative :package-present-by :found - :suggestion-attempt :unsuccessful }))) + :suggestion-attempt :unsuccessful })) (= status :absent) (resolve-deps repo From bb28089974e2b00bae895f1b1d3e65ce28aee5c6 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Thu, 29 Aug 2019 16:40:12 -0600 Subject: [PATCH 25/41] Fix bugs related to version suggestion --- src/degasolv/resolver_core.clj | 13 +++++++++---- test/degasolv/resolver/unsuccessful_test.clj | 4 ++-- test/degasolv/resolver/version_suggestions.clj | 4 ++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/degasolv/resolver_core.clj b/src/degasolv/resolver_core.clj index df23415..9b17c6d 100644 --- a/src/degasolv/resolver_core.clj +++ b/src/degasolv/resolver_core.clj @@ -389,25 +389,30 @@ vet candidates] (loop [remaining candidates - failure-record {}] - (dbg remaining) + failure-record {} + previously-examined #{}] (if (empty? remaining) [:unsuccessful failure-record] (let [fcand (first remaining) rcand (rest remaining) id (:id fcand) + already-seen (conj previously-examined fcand) [status result :as response] (try-candidate fcand)] (if (successful? response) response (recur (if-let [relevant-suggestions (get (:suggestions result) id)] - (into (set/select vet relevant-suggestions) + (into (set/select (fn [y] + (and (not (already-seen y)) + (vet y))) + relevant-suggestions) rcand) rcand) - (merge-failure-records failure-record result))))))) + (merge-failure-records failure-record result) + already-seen)))))) (defn make-resolve-deps [conflict-strat diff --git a/test/degasolv/resolver/unsuccessful_test.clj b/test/degasolv/resolver/unsuccessful_test.clj index d9ed4f0..f4f9df3 100644 --- a/test/degasolv/resolver/unsuccessful_test.clj +++ b/test/degasolv/resolver/unsuccessful_test.clj @@ -180,7 +180,7 @@ :found-packages {"a" [a2] "b" - [b3]} + [b2]} :present-packages {} :absent-specs {} :reason :package-not-found @@ -190,7 +190,7 @@ :found-packages {"a" [a2] "b" - [b2]} + [b3]} :present-packages {} :absent-specs {} :reason :package-not-found diff --git a/test/degasolv/resolver/version_suggestions.clj b/test/degasolv/resolver/version_suggestions.clj index 7100f19..2618334 100644 --- a/test/degasolv/resolver/version_suggestions.clj +++ b/test/degasolv/resolver/version_suggestions.clj @@ -70,8 +70,8 @@ (testing "Make sure that the bomb version (c20) is skipped." (is (.equals [:successful #{a b c30}] - (dbg (resolve-dependencies + (resolve-dependencies [ [(present "a")] ] - query-asc)))))))) + query-asc))))))) From 50062e9f2974c58d85a1db983dd457e9e8e801c0 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Thu, 29 Aug 2019 22:17:10 -0600 Subject: [PATCH 26/41] Update changelog for version suggestion --- docs/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 66201d1..396f6dd 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -17,6 +17,8 @@ and this project adheres to `Semantic Versioning`_. Added +++++ +- Added version suggestion, allowing for minimum version selection + - If the reason for failure in the ``resolve-dependencies`` function is ``:present-package-conflict``, add a key ``:package-present-by`` with value as either ``:found`` meaning the package was in conflict with a package From 858383b3cd2717953fde5a579ec52db2ca58284d Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 11 Sep 2019 13:38:45 -0600 Subject: [PATCH 27/41] Probably will break things but --- src/degasolv/resolver_spec.clj | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/degasolv/resolver_spec.clj b/src/degasolv/resolver_spec.clj index dd86d3d..d7ebae1 100644 --- a/src/degasolv/resolver_spec.clj +++ b/src/degasolv/resolver_spec.clj @@ -6,11 +6,15 @@ :greater-equal :greater-than}) +(def str-id-pattern "[^!=<>]*") +(def id-regex (re-pattern (str "^" str-id-pattern "$"))) + (s/def ::id (s/and string? - #(not (empty? %)))) + #(re-matches #"^[^!=<>]+$") + #(re-matches #"^\p{Print}+$"))) -(def str-version-pattern "[A-Za-z0-9][A-Za-z0-9]*([.-][A-Za-z0-9]+)*") +(def str-version-pattern "(\\p{Alnum}|\\p{Punct})*") (def version-regex (re-pattern (str "^" @@ -72,6 +76,7 @@ ::package :into []))) + (def str-equals-pattern "==") (def str-relation-pattern "(>=|==|!=|<=|<|>)") (def str-id-pattern "[^>= Date: Sun, 27 Oct 2019 10:52:03 -0600 Subject: [PATCH 28/41] Clarify what was added --- .gitignore | 1 + docs/changelog.rst | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f8220bc..4452d1b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target +.cpcache /pkg/ /presentation/target/ /presentation/auto/ diff --git a/docs/changelog.rst b/docs/changelog.rst index 396f6dd..3c55ac2 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -17,7 +17,8 @@ and this project adheres to `Semantic Versioning`_. Added +++++ -- Added version suggestion, allowing for minimum version selection +- Added version suggestion, a performance enhancement allowing for minimum + version selection - If the reason for failure in the ``resolve-dependencies`` function is ``:present-package-conflict``, add a key ``:package-present-by`` with From e95d4b3d33981257cac966a9b3810a7710235aff Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Tue, 29 Oct 2019 12:25:28 -0600 Subject: [PATCH 29/41] Fix roadmap --- bisect.sh | 6 ++ docs/roadmap.rst | 231 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 209 insertions(+), 28 deletions(-) create mode 100755 bisect.sh diff --git a/bisect.sh b/bisect.sh new file mode 100755 index 0000000..3d59fb8 --- /dev/null +++ b/bisect.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -ex +rm -rf target/ +lein uberjar +test/resources/scripts/test-list-strat diff --git a/docs/roadmap.rst b/docs/roadmap.rst index b080f58..a17507e 100644 --- a/docs/roadmap.rst +++ b/docs/roadmap.rst @@ -1,34 +1,212 @@ Roadmap ======= -This document is intended to help guide what features are upcoming in degasolv. -Some of these features are aspirational; that is, we want to implement them, -but may not be able to or may decide later that we didn't really want that -after all. Nevertheless, for what it's worth, here is the current roadmap. +This file outlines what we plan on doing to democratize dependency management. +It may or may not actually be implemented in the future, but represents a guide +for contributors and users alike as to the hopes and vision for the future of +the Degasolv developers. + +Future Releases +--------------- + +- [ ] Tutorial-like help screens designed to keep people from needing to switch + from docs to cli and back. + +- [ ] Shortened versions of all subcommands, including documentation updates. + +- [ ] Environment-variable specification of options: the ability to specify + options using environment variables. Options taking a list will accept + comma-separated lists in the environment variable. Commas in strings + as values in these lists will simply not be supported in the initial version. + +- [ ] Authenticated HTTP and HTTPS connections: we will provide a way by which + HTTP and HTTPS connections are authenticated, I think using a .netrc-like + mapping between hosts and username/password pairs. Documentation should be + written around specifying username and password securely according to needs, + whether by standard input using the conventional config file mechanisms, by + environment variable, or by command line. Each has security implications that + the user needs to be aware of. + +- [ ] Documentation and/or code on the topic of supporting the use case of + different architectures of the same package using prioritized indexes of + packages named the same with different contents. + +- [ ] **Compile with GraalVM's ``native-image``**: Compile degasolv to machine + code with GraalVM's ``native-image`` to decrease start-up times. This will likely + coincide with upgrading to Clojure 1.11 because native-image doesn't work with + Clojure 1.10.1 . + +2.2.0 +----- + +Package Installation Manager +++++++++++++++++++++++++++++ + +This is what has been missing from Degasolv for a long time: the notion of an +installation. We've got dependency management down; now we need to get into +installation management. + +In keeping with Degasolv's original vision, we will *not* make specific what +is actually being installed or maintained. This way, Degasolv can be kept +as a neutral, generic tool that can apply in many situations. Firefighters +need tools that can apply in many situations; similarly, ops and DevOps +professionals, for whom we build this tool, need to a dependency management +tool that can get them out of dependency hell no matter what their situation. + +Therefore, we focus on two explicit dimensions of installation management, the +"hard parts", and leave the implementation details like unpacking archives and +writing to file or key-value stores to the DevOps professional. + +These are: +1. Resource management +2. Package installation database + +An Installation Database +++++++++++++++++++++++++ + +A new database that represents a particular package "installation". This could +be used for a file installation, a kubernetes/windows/whatever installation. + +package installation will house: +- Site-wide configuration +- Packages that have been installed and the relationships between them + +This database will allow us to track and manage: +- package installations +- package removals +- package verification + +- [ ] A new global option, ``--installation``, that would take a JDBC + connection string. If the option ``--ignore-installation`` were also + present any functionality would be turned off, including ignoring the + installation for configuration items. An optional username and password + for the connection, ``--installation-username``, and ``--installation-password``, + would be allowed. Last wins. Documentation should be written around + specifying username and password securely according to needs, whether by + standard input using the conventional config file mechanisms, by + environment variable, or by command line. Each has security implications + that the user needs to be aware of. + +- [ ] If the ``--installation`` option is present, the ``resolve-locations`` + subcommand would take the installation into account in its resolution as + present packages. + +- [ ] If the ``--enable-installation-only`` is present, the ``resolve-locations`` + subcommand would take the installation into account as its sole index. + Any subsequent options given for other indices will be recorded, but + ignored. These will be turned "back on" if the option + ``--disable-installation-only`` is encountered. + +- [ ] If the ``--enable-from-installation`` is present, the ``resolve-locations`` + subcommand would take the installation into account as one of its + indexes in "the usual order", as if it were another specified index + on the commandline. Its order will be reset if it is encountered again. + It can be turned off with ``--disable-from-installation``. Last wins. + +- [ ] A new subcommand, ``init-installation``, would require that ``--installation`` were given, + optional username and password for the + connection. It would record present configuration (that is, + configuration as observed by init-installation), + and set up the necessary tables for future use. + +- [ ] A new subcommand, ``resolve-dependents``, that takes an installation, + package and version (presumably installed) and lists all packages and + versions that depend on that version of that package. + + - [ ] A new function, ``resolve-dependents``, that takes a package and version + and query function and uses the query function to determine + what other packages depend on the current package, recursively. + +- [ ] A new subcommand, ``install-package``, that would take a plain list or + json blob of packages and installs them provided their resources + were mutually exclusive with each other and all installed packages + (see below) and provided their dependencies were met. this can easily + be done by calling ``resolve-dependencies`` with a nullary query function + and big list of packages to install. Dependencies will not be checked + if ``--force`` is present. + +- [ ] A new subcommand, ``remove-package``, that would take a plain list or + json blob of packages and remove them provided all dependencies were met. + Package dependencies will not be checked if ``--force`` is present. + +- [ ] A new subcommand, ``list-packages``, that would yield to standard out + a plain/json list of packages from an installation. It would take an + optional parameter that lists out a particular package at a particular version, + or all packages matching only a package name. + +A New Notion of Resources ++++++++++++++++++++++++++ + +As part of this new initiative, packages will be given a new attribute called +"resources". This attribute will house a map from resource type names to a map +of resource states. This map will map a resources to their states upon +installation. Both resources and resource states are simply strings. Meta +information under the ``meta`` key will also be stored. + +For example, resources could be files and states could be sha256 hashes, +with any metadata about the files, like whether they are config or not:: + + { + "files": { + "/var/lib/foo": { + "state": "600dc0d36077a10ada600dd3a10fda7a600dc0d36077a10ada600dd3a10fda7a", + "meta": { + "tags": ["config"] + } + } + } + } + +With this new notion of resources, resource management can be correctly +implemented upon package installation, removal, creation, and verification. + +- [ ] A new option needs to be added to ``generate-card`` to specify resources. + This would be an executable that would take a package name, version and + location and would return resources in JSON over standard output. + +- [ ] A new subcommand, ``verify-package``, needs to be created that verifies + listed package resources against listed resources. This would take an + executable as an option that took the name and type of a resource and yielded + a string on standard output that would be the state. A diff of the supposed + state and the actual state would be printed. If no arguments are given, it + lists verification information for all such packages, plain/json. + +- [ ] A feature of ``install-package``: A package can only be installed if + no package, currently being installed or previously installed, + installs the same resources. 2.1.0 ----- -- **Minimum Version Selection**: Implement minimum version selection as an +- [ ] **Minimum Version Selection**: Implement minimum version selection as an option pack. Supporting features: - - Version suggestion: when trying different candidates, if a matching id is - in the return of a candidate, put the suggestions in the list to loop - through. - - Skip unlikely candidates: Keep a set of problem ids different candidates - are tried. If the current alternative's ID is not in that set, and if the - dependencies are the same as the previous candidate, then skip the - candidate; do not try it. - - Minimum version preference: In generate repo index, add option to sort - packages the other way. - - Proper documentation surrounding order of encounter, that for example for - subproc degasolv will honor the order of packages found in the repo index - and that this enables things like MVS. - -- **Git package system**: Implement git package system that knows how to - read bitbucket, bitbucket server, github, github server, gitlab, gitlab - server, and raw git repos. - -- **Inclusive/Absent corner case**: In the case that ``conflict-strat`` is + - [x] Version suggestion: when trying different candidates, if a matching + id is in the return of a candidate, put the suggestions in the list to + loop through. + + - CANCELLED: Skip unlikely candidates: Keep a set of problem ids different + candidates are tried. If the current alternative's ID is not in that set, + and if the dependencies are the same as the previous candidate, then skip + the candidate; do not try it. + + This was cancelled because it was not needed to implement version + suggestion, when at first I thought I would need it. + + - [ ] Minimum version preference: In generate repo index, add option to + sort packages the other way. + + - [ ] Proper documentation surrounding order of encounter, that for example + for subproc degasolv will honor the order of packages found in the repo + index and that this enables things like MVS. + +- CANCELLED: **Git package system**: Implement git package system that knows + how to read bitbucket, bitbucket server, github, github server, gitlab, + gitlab server, and raw git repos. This was cancelled because it felt "out of + scope"; i didn't want to build ever-changing vendor-specific API details into + a tool I hope will be a more generic tool that outlasts these APIs. + I think git integrations is the subject for a good but different tool. + +- [ ] **Inclusive/Absent corner case**: In the case that ``conflict-strat`` is inclusive, a case may arise where an absence is required, but then another requirement asks for the same package to be present at a conflicting version. basically, what do requirements of absence mean within and inclusive context. @@ -36,9 +214,6 @@ after all. Nevertheless, for what it's worth, here is the current roadmap. in inclusive contexts. This seems silly. Requirements of absence should just be ignored when ``conflict-strat`` is ``inclusive``. -- Fix #17, it is awful. +- [ ] Fix #17, it is awful. + -Future Features ---------------- -- **Compile with GraalVM's ``native-image``**: Compile degasolv to machine - code with GraalVM's ``native-image`` to decrease start-up times. From ec98d70d9bf1beebe5710262645660b00776fc5b Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Tue, 29 Oct 2019 13:30:28 -0600 Subject: [PATCH 30/41] 'Probably will break things but' TOTALLY broke things --- src/degasolv/resolver_spec.clj | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/degasolv/resolver_spec.clj b/src/degasolv/resolver_spec.clj index d7ebae1..430a25b 100644 --- a/src/degasolv/resolver_spec.clj +++ b/src/degasolv/resolver_spec.clj @@ -6,13 +6,13 @@ :greater-equal :greater-than}) -(def str-id-pattern "[^!=<>]*") +(def str-id-pattern "[^>=]+$") - #(re-matches #"^\p{Print}+$"))) + #(re-matches id-regex %) + #(re-matches #"^\p{Print}+$" %))) (def str-version-pattern "(\\p{Alnum}|\\p{Punct})*") @@ -79,7 +79,6 @@ (def str-equals-pattern "==") (def str-relation-pattern "(>=|==|!=|<=|<|>)") -(def str-id-pattern "[^>= Date: Tue, 29 Oct 2019 13:36:04 -0600 Subject: [PATCH 31/41] Fix id spec --- docs/changelog.rst | 5 +++++ src/degasolv/resolver_spec.clj | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 3c55ac2..bffa313 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -39,6 +39,11 @@ Fixed - Fix #16 +- Fix spec for package id's. This should have the effect of enforcing that + names should not have ``>``, ``<``, ``!``, ``=``, ``,``, ``;``, or ``|`` + characters in them. This simply has the effect of changing the error message, + as this was never allowed but handled poorly. + `2.0.0`_ -------- diff --git a/src/degasolv/resolver_spec.clj b/src/degasolv/resolver_spec.clj index 430a25b..d1b2bce 100644 --- a/src/degasolv/resolver_spec.clj +++ b/src/degasolv/resolver_spec.clj @@ -11,8 +11,7 @@ (s/def ::id (s/and string? - #(re-matches id-regex %) - #(re-matches #"^\p{Print}+$" %))) + #(re-matches id-regex %))) (def str-version-pattern "(\\p{Alnum}|\\p{Punct})*") From 9d797e7477dba78631856b2263501c6e5112ece7 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Tue, 29 Oct 2019 14:29:48 -0600 Subject: [PATCH 32/41] Update build --- .circleci/config.yml | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2875986..2fc2054 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -92,7 +92,7 @@ jobs: - checkout - run: cp -af /tmp/workspace/target ./ - run: - name: "Package debian for CentOS 7" + name: "Package rpm for CentOS 7" command: buildutils/package rpm no_output_timeout: 30m - run: mv target/package target/package_c7 @@ -104,6 +104,28 @@ jobs: path: target/package_c7/ destination: package_c7/ + package_centos8: + docker: + - image: djhaskin987/graal-lein-fpm:centos8 + version: 2 + steps: + - attach_workspace: + at: /tmp/workspace + - checkout + - run: cp -af /tmp/workspace/target ./ + - run: + name: "Package rpm for CentOS 8" + command: buildutils/package rpm + no_output_timeout: 30m + - run: mv target/package target/package_c8 + - persist_to_workspace: + root: . + paths: + - target/package_c8/*.rpm + - store_artifacts: + path: target/package_c8/ + destination: package_c8/ + test_ubuntu16_package: docker: - image: djhaskin987/test-ubuntu-installer:ubuntu16 @@ -130,7 +152,7 @@ jobs: test_centos7_package: docker: - - image: bzohdy/centos-sudo:latest + - image: djhaskin987/test-centos-installer:centos7 version: 2 steps: - attach_workspace: @@ -140,6 +162,18 @@ jobs: - run: mv target/package_c7 target/package - run: buildutils/test-install-package-centos + test_centos8_package: + docker: + - image: djhaskin987/test-centos-installer:centos8 + version: 2 + steps: + - attach_workspace: + at: /tmp/workspace + - checkout + - run: cp -af /tmp/workspace/target ./ + - run: mv target/package_c8 target/package + - run: buildutils/test-install-package-centos + workflows: version: 2 build_and_test: @@ -155,6 +189,9 @@ workflows: - package_centos7: requires: - lein_tests + - package_centos8: + requires: + - lein_tests - test_ubuntu16_package: requires: - package_ubuntu16 @@ -164,3 +201,6 @@ workflows: - test_centos7_package: requires: - package_centos7 + - test_centos8_package: + requires: + - package_centos8 From defa8d9bd830384b64b0a3efa44b11e1a6a4bf0f Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Tue, 29 Oct 2019 14:59:50 -0600 Subject: [PATCH 33/41] Fix roadmap --- docs/roadmap.rst | 67 ++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/docs/roadmap.rst b/docs/roadmap.rst index a17507e..62a1746 100644 --- a/docs/roadmap.rst +++ b/docs/roadmap.rst @@ -103,36 +103,36 @@ This database will allow us to track and manage: on the commandline. Its order will be reset if it is encountered again. It can be turned off with ``--disable-from-installation``. Last wins. -- [ ] A new subcommand, ``init-installation``, would require that ``--installation`` were given, - optional username and password for the - connection. It would record present configuration (that is, - configuration as observed by init-installation), - and set up the necessary tables for future use. +- [ ] A new subcommand, ``init-installation``, would require that + ``--installation`` were given, optional username and password for the + connection. It would record present configuration (that is, configuration as + observed by init-installation), and set up the necessary tables for future + use. - [ ] A new subcommand, ``resolve-dependents``, that takes an installation, - package and version (presumably installed) and lists all packages and - versions that depend on that version of that package. + package and version (presumably installed) and lists all packages and + versions that depend on that version of that package. - - [ ] A new function, ``resolve-dependents``, that takes a package and version - and query function and uses the query function to determine - what other packages depend on the current package, recursively. + - [ ] A new function, ``resolve-dependents``, that takes a package and + version and query function and uses the query function to determine + what other packages depend on the current package, recursively. - [ ] A new subcommand, ``install-package``, that would take a plain list or - json blob of packages and installs them provided their resources - were mutually exclusive with each other and all installed packages - (see below) and provided their dependencies were met. this can easily - be done by calling ``resolve-dependencies`` with a nullary query function - and big list of packages to install. Dependencies will not be checked - if ``--force`` is present. + json blob of packages and installs them provided their resources were + mutually exclusive with each other and all installed packages (see below) and + provided their dependencies were met. this can easily be done by calling + ``resolve-dependencies`` with a nullary query function and big list of + packages to install. Dependencies will not be checked if ``--force`` is + present. - [ ] A new subcommand, ``remove-package``, that would take a plain list or - json blob of packages and remove them provided all dependencies were met. - Package dependencies will not be checked if ``--force`` is present. + json blob of packages and remove them provided all dependencies were met. + Package dependencies will not be checked if ``--force`` is present. -- [ ] A new subcommand, ``list-packages``, that would yield to standard out - a plain/json list of packages from an installation. It would take an - optional parameter that lists out a particular package at a particular version, - or all packages matching only a package name. +- [ ] A new subcommand, ``list-packages``, that would yield to standard out a + plain/json list of packages from an installation. It would take an optional + parameter that lists out a particular package at a particular version, or all + packages matching only a package name. A New Notion of Resources +++++++++++++++++++++++++ @@ -161,19 +161,19 @@ With this new notion of resources, resource management can be correctly implemented upon package installation, removal, creation, and verification. - [ ] A new option needs to be added to ``generate-card`` to specify resources. - This would be an executable that would take a package name, version and - location and would return resources in JSON over standard output. + This would be an executable that would take a package name, version and + location and would return resources in JSON over standard output. - [ ] A new subcommand, ``verify-package``, needs to be created that verifies - listed package resources against listed resources. This would take an - executable as an option that took the name and type of a resource and yielded - a string on standard output that would be the state. A diff of the supposed - state and the actual state would be printed. If no arguments are given, it - lists verification information for all such packages, plain/json. + listed package resources against listed resources. This would take an + executable as an option that took the name and type of a resource and yielded + a string on standard output that would be the state. A diff of the supposed + state and the actual state would be printed. If no arguments are given, it + lists verification information for all such packages, plain/json. -- [ ] A feature of ``install-package``: A package can only be installed if - no package, currently being installed or previously installed, - installs the same resources. +- [ ] A feature of ``install-package``: A package can only be installed if no + package, currently being installed or previously installed, installs the same + resources. 2.1.0 ----- @@ -189,8 +189,7 @@ implemented upon package installation, removal, creation, and verification. and if the dependencies are the same as the previous candidate, then skip the candidate; do not try it. - This was cancelled because it was not needed to implement version - suggestion, when at first I thought I would need it. + This was cancelled because it was problematic. - [ ] Minimum version preference: In generate repo index, add option to sort packages the other way. From 81ee728cc7b17df2681de831e10dd223b405ff44 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Tue, 29 Oct 2019 15:31:10 -0600 Subject: [PATCH 34/41] Add sort order to generate-repo-index --- src/degasolv/cli.clj | 24 ++++++++++++++++++++++-- src/degasolv/pkgsys/core.clj | 10 ++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/degasolv/cli.clj b/src/degasolv/cli.clj index 3405f32..21adedd 100644 --- a/src/degasolv/cli.clj +++ b/src/degasolv/cli.clj @@ -206,12 +206,24 @@ (let [{:keys [search-directory index-file version-comparison - add-to]} options] + add-to + index-sort-order + ]} options + sortindex + (if (= index-sort-order "as-is") + (fn [x] x) + (let [vercmp (if (= index-sort-order "ascending") + #(version-comparison (:version %1) + (:version %2)) + #(- (version-comparison + (:version %1) + (:version %2))))] + (fn [x] (into [] (sort vercmp (second x))))))] (degasolv-pkg/generate-repo-index! search-directory index-file add-to - (get version-comparators version-comparison)))) + sortindex))) (defn- aggregate-repositories [index-strat @@ -476,6 +488,7 @@ :conflict-strat "exclusive" :index-file "index.dsrepo" :index-strat "priority" + :index-sort-order "descending" :output-format "plain" :subproc-output-format "json" :package-system "degasolv" @@ -602,6 +615,13 @@ (and (.isDirectory ^java.io.File f) (.exists ^java.io.File f))) "Must be a directory which exists on the file system."]] + + ["-O" "--index-sort-order ORDER" + "May be 'ascending', 'descending' or 'as-is'." + :default nil + :default-desc "descending" + :validate [#(some #{%} ["ascending" "descending" "as-is"]) + "Index sort order may be 'ascending', 'descending' or 'as-is'."]] ["-I" "--index-file FILE" "The name of the repo file" :default nil diff --git a/src/degasolv/pkgsys/core.clj b/src/degasolv/pkgsys/core.clj index 5feec32..9c785a6 100644 --- a/src/degasolv/pkgsys/core.clj +++ b/src/degasolv/pkgsys/core.clj @@ -29,24 +29,22 @@ [search-directory index-file add-to - version-comparator + sortindex ] (let [output-file index-file initial-repository (if add-to (tag/read-string (default-slurp add-to)) - (hash-map))] + (hash-map)) + ] (default-spit output-file (into (hash-map) (map (fn [x] [(first x) - (into [] - (sort #(- (version-comparator (:version %1) - (:version %2))) - (second x)))]) + (sortindex (second x))]) (reduce (fn merg [c v] (update-in c [(:id v)] conj v)) From 8506995abbeb1d8e2e2bd1d7e28bb9eb68c5d2ec Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Tue, 29 Oct 2019 15:42:25 -0600 Subject: [PATCH 35/41] Fix index sort order --- .gitignore | 9 ++-- src/degasolv/cli.clj | 2 +- test/resources/scripts/test-index-sort-order | 55 ++++++++++++++++++++ test/resources/scripts/test-output-format | 2 +- 4 files changed, 62 insertions(+), 6 deletions(-) create mode 100755 test/resources/scripts/test-index-sort-order diff --git a/.gitignore b/.gitignore index 4452d1b..9c38d11 100644 --- a/.gitignore +++ b/.gitignore @@ -20,13 +20,14 @@ /test-data/ /test/resources/data/grill/ /test/resources/data/meta/ +/test/resources/data/test-index-sort-order/ +/test/resources/data/test-json-config/ +/test/resources/data/test-list-strat/ +/test/resources/data/test-option-packs/ +/test/resources/data/test-query-output-format/ /test/resources/data/test-search-strat/ /test/resources/data/test-version-comparison/ /test/resources/test-data/ -/test/resources/data/test-option-packs/ -/test/resources/data/test-json-config/ -/test/resources/data/test-query-output-format/ -/test/resources/data/test-list-strat/ /buildutils/boot /degasolv-*-standalone /*.dscard diff --git a/src/degasolv/cli.clj b/src/degasolv/cli.clj index 21adedd..a84e244 100644 --- a/src/degasolv/cli.clj +++ b/src/degasolv/cli.clj @@ -218,7 +218,7 @@ #(- (version-comparison (:version %1) (:version %2))))] - (fn [x] (into [] (sort vercmp (second x))))))] + (fn [x] (into [] (sort vercmp x)))))] (degasolv-pkg/generate-repo-index! search-directory index-file diff --git a/test/resources/scripts/test-index-sort-order b/test/resources/scripts/test-index-sort-order new file mode 100755 index 0000000..2078062 --- /dev/null +++ b/test/resources/scripts/test-index-sort-order @@ -0,0 +1,55 @@ +#!/bin/sh +set -eoux + +export POSIXLY_CORRECT=1 + +if [ ! -f './project.clj' -a ! -f './build.boot' ] +then + echo "This script must be run from the root of the project." +fi + +root_path=${PWD} +test_home=test/resources/data/test-index-sort-order + +name=$(lein print :name | sed 's|"||g') +version=$(lein print :version | sed 's|"||g') + +rm -rf "${test_home}" +mkdir -p "${test_home}" +cd "${test_home}" + +# First, generate the needed cards for resolution. + +java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar \ + generate-card \ + -i "a" \ + -v "1.0.0" \ + -l "https://example.com/repo/a-1.0.0.zip" \ + -C $PWD/a-1.0.0.zip.dscard + +java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar \ + generate-card \ + -i "a" \ + -v "2.0.0" \ + -l "https://example.com/repo/a-2.0.0.zip" \ + -C $PWD/a-2.0.0.zip.dscard + +java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar generate-repo-index -O ascending -d $PWD -I $PWD/ascending.dsrepo + +java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar generate-repo-index -O descending -d $PWD -I $PWD/descending.dsrepo + +if java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar \ + resolve-locations \ + -R ${PWD}/descending.dsrepo \ + --requirement "a" | grep -F -q '1.0.0' +then + exit 1 +fi + +if java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar \ + resolve-locations \ + -R ${PWD}/ascending.dsrepo \ + --requirement "a" | grep -F -q '2.0.0' +then + exit 1 +fi diff --git a/test/resources/scripts/test-output-format b/test/resources/scripts/test-output-format index b54becf..cfb780a 100755 --- a/test/resources/scripts/test-output-format +++ b/test/resources/scripts/test-output-format @@ -9,7 +9,7 @@ then fi root_path=${PWD} -test_home=test/resources/data/test-version-comparison +test_home=test/resources/data/test-output-format name=$(lein print :name | sed 's|"||g') version=$(lein print :version | sed 's|"||g') From adf183dc6f32331f9034b4b9c6d50d748488a2e0 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Tue, 29 Oct 2019 15:47:47 -0600 Subject: [PATCH 36/41] improve test-index-sort-order, fix it in cli --- src/degasolv/cli.clj | 5 +++-- test/resources/scripts/test-index-sort-order | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/degasolv/cli.clj b/src/degasolv/cli.clj index a84e244..49c6277 100644 --- a/src/degasolv/cli.clj +++ b/src/degasolv/cli.clj @@ -209,13 +209,14 @@ add-to index-sort-order ]} options + version-comparator (get version-comparators version-comparison) sortindex (if (= index-sort-order "as-is") (fn [x] x) (let [vercmp (if (= index-sort-order "ascending") - #(version-comparison (:version %1) + #(version-comparator (:version %1) (:version %2)) - #(- (version-comparison + #(- (version-comparator (:version %1) (:version %2))))] (fn [x] (into [] (sort vercmp x)))))] diff --git a/test/resources/scripts/test-index-sort-order b/test/resources/scripts/test-index-sort-order index 2078062..c3facb7 100755 --- a/test/resources/scripts/test-index-sort-order +++ b/test/resources/scripts/test-index-sort-order @@ -36,7 +36,7 @@ java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar \ java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar generate-repo-index -O ascending -d $PWD -I $PWD/ascending.dsrepo -java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar generate-repo-index -O descending -d $PWD -I $PWD/descending.dsrepo +java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar generate-repo-index --index-sort-order descending -d $PWD -I $PWD/descending.dsrepo if java -jar ${root_path}/target/uberjar/${name}-${version}-standalone.jar \ resolve-locations \ From 2669a9021bc14f04356b51a31d0d2e494e92a48c Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 30 Oct 2019 17:14:34 -0600 Subject: [PATCH 37/41] Remove as-is, it makes no sense --- src/degasolv/cli.clj | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/degasolv/cli.clj b/src/degasolv/cli.clj index 49c6277..c116eef 100644 --- a/src/degasolv/cli.clj +++ b/src/degasolv/cli.clj @@ -211,15 +211,13 @@ ]} options version-comparator (get version-comparators version-comparison) sortindex - (if (= index-sort-order "as-is") - (fn [x] x) - (let [vercmp (if (= index-sort-order "ascending") - #(version-comparator (:version %1) - (:version %2)) - #(- (version-comparator - (:version %1) - (:version %2))))] - (fn [x] (into [] (sort vercmp x)))))] + (let [vercmp (if (= index-sort-order "ascending") + #(version-comparator (:version %1) + (:version %2)) + #(- (version-comparator + (:version %1) + (:version %2))))] + (fn [x] (into [] (sort vercmp x))))] (degasolv-pkg/generate-repo-index! search-directory index-file @@ -616,13 +614,12 @@ (and (.isDirectory ^java.io.File f) (.exists ^java.io.File f))) "Must be a directory which exists on the file system."]] - ["-O" "--index-sort-order ORDER" - "May be 'ascending', 'descending' or 'as-is'." + "May be 'ascending' or 'descending'." :default nil :default-desc "descending" - :validate [#(some #{%} ["ascending" "descending" "as-is"]) - "Index sort order may be 'ascending', 'descending' or 'as-is'."]] + :validate [#(some #{%} ["ascending" "descending"]) + "Index sort order may be 'ascending' or 'descending'."]] ["-I" "--index-file FILE" "The name of the repo file" :default nil From f88b709f8d0624157a700656af59375d348f30c3 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 30 Oct 2019 18:50:51 -0600 Subject: [PATCH 38/41] Alphabetize command options --- src/degasolv/cli.clj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/degasolv/cli.clj b/src/degasolv/cli.clj index c116eef..4d5195b 100644 --- a/src/degasolv/cli.clj +++ b/src/degasolv/cli.clj @@ -614,16 +614,16 @@ (and (.isDirectory ^java.io.File f) (.exists ^java.io.File f))) "Must be a directory which exists on the file system."]] + ["-I" "--index-file FILE" + "The name of the repo file" + :default nil + :default-desc (str (:index-file subcommand-option-defaults))] ["-O" "--index-sort-order ORDER" "May be 'ascending' or 'descending'." :default nil :default-desc "descending" :validate [#(some #{%} ["ascending" "descending"]) "Index sort order may be 'ascending' or 'descending'."]] - ["-I" "--index-file FILE" - "The name of the repo file" - :default nil - :default-desc (str (:index-file subcommand-option-defaults))] ["-V" "--version-comparison CMP" "May be 'debian', 'maven', 'naive', 'python', 'rpm', 'rubygem', or 'semver'." :default nil From 0b393dc799d79533cb67fe80b67913bf4a0eff8f Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Wed, 30 Oct 2019 18:51:08 -0600 Subject: [PATCH 39/41] Update docs in preparation for release of 2.1.0 --- docs/architecture.rst | 8 +++--- docs/changelog.rst | 19 +++++++++++---- docs/command-reference.rst | 50 ++++++++++++++++++++++++++++++++++---- docs/contributing.rst | 35 +++++++++++++++++--------- docs/get-degasolv.rst | 5 ++-- 5 files changed, 90 insertions(+), 27 deletions(-) diff --git a/docs/architecture.rst b/docs/architecture.rst index ad79ec3..5b3859a 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -31,15 +31,15 @@ So I decided to build a tool that would do these things: Core Resolver ------------- -At the core of degasolv is a monster method called `resolve-dependencies`_. It +At the core of Degasolv is a monster method called `resolve-dependencies`_. It is a rather large method with a backtracking SAT-solver-ish design. Originally it was written to have a :ref:`conflict-strat` of ``exclusive`` and a :ref:`resolve-strat` of ``thorough`` hard-coded. In other -words, the "first class" original use case of degasolv was a SAT-solver-class +words, the "first class" original use case of Degasolv was a SAT-solver-class depedency resolver that only allowed a single version of any dependency, and ensured that all parties depending on that dependency had a chance to agree on -what was chosen. These options were later added to allow degasolv to act more -like maven and give any Building Engineer using degasolv useful "handbreaks" to +what was chosen. These options were later added to allow Degasolv to act more +like maven and give any Building Engineer using Degasolv useful "handbreaks" to change how resolution was being done in-house so that it could be modified to conform to business needs. Other options, such as `list-strat` and `search-strat` were added as time progressed as well for similar diff --git a/docs/changelog.rst b/docs/changelog.rst index bffa313..923f1da 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -17,9 +17,15 @@ and this project adheres to `Semantic Versioning`_. Added +++++ -- Added version suggestion, a performance enhancement allowing for minimum +- Added "version suggestion", a performance enhancement allowing for minimum version selection +- Added the ``:index-sort-order`` option to ``generate-repo-index``, + allowing users to specify ``ascending`` or ``descending``. Previously + only ``descending`` was supported. With this new option, + users will be able to use Degasolv in a minimum version selection + configuration. + - If the reason for failure in the ``resolve-dependencies`` function is ``:present-package-conflict``, add a key ``:package-present-by`` with value as either ``:found`` meaning the package was in conflict with a package @@ -37,6 +43,9 @@ Changed Fixed +++++ +- Standardized capitalization of the word "Degasolv" to be title case for + consistency in the documentation unless it is in a code snippet. + - Fix #16 - Fix spec for package id's. This should have the effect of enforcing that @@ -74,7 +83,7 @@ Changed ` set to ``lazy``, a much saner default. - Option pack ``v1`` :ref:`added ` to help administrators - keep compatibility with version 1 of degasolv if required. + keep compatibility with version 1 of Degasolv if required. - Default for the ``--version-comparison`` option when ``--package-system`` is ``degasolv`` set to ``semver`` for @@ -102,7 +111,7 @@ Fixed - Fixed #9, "Heading for 'Specifying Subproc Executable' is wrong in docs" - Fixed #10, "How do you specify requirements of a package (deps) in the output - of a subproc to degasolv?" + of a subproc to Degasolv?" `1.12.1`_ --------- @@ -282,7 +291,7 @@ Added Fixed +++++ -- While using the apt data and package system to profile degasolv, I +- While using the apt data and package system to profile Degasolv, I found some rather nasty bugs. This release fixes them. This tool is now ready for prime time. @@ -304,7 +313,7 @@ Added - Added the ``--present-package`` :ref:`option ` and the ``--package-system`` :ref:`option ` to the :ref:`resolve-locations ` subcommand. This was so - that degasolv could be profiled using apt package repos + that Degasolv could be profiled using apt package repos (real-world data) and thereby have its performance optimized. `1.3.0`_ diff --git a/docs/command-reference.rst b/docs/command-reference.rst index d6bc2d3..2e04275 100644 --- a/docs/command-reference.rst +++ b/docs/command-reference.rst @@ -60,7 +60,7 @@ a page that looks something like this:: .. note:: In this guide, for brevity, the reference is presented - as if the command to execute degasolv were simply ``degasolv`` rather + as if the command to execute Degasolv were simply ``degasolv`` rather than the more correct ``java -jar degasolv--standalone.jar``. A bash or batch script can easily be made to turn one command into the other, and the change was made to the former form for clarity. @@ -70,7 +70,7 @@ a page that looks something like this:: A Note on Specifying Files ++++++++++++++++++++++++++ -As of version 1.3.0, The whenever an option takes a file in degasolv, +As of version 1.3.0, The whenever an option takes a file in Degasolv, the user can actually specify one of three things: 1. An ``http://`` or ``https://`` URL. No authentication is @@ -358,8 +358,8 @@ the config file are ignored. The following option packs are supported in the current version: - ``v1``: Added as of version 2.0.0 . Implies ``--list-strat as-set`` and ``--disable-error-format``. This - pack was added to help support legacy deployments of degasolv. - It should be noted that to achieve full compatibility with degasolv + pack was added to help support legacy deployments of Degasolv. + It should be noted that to achieve full compatibility with Degasolv version 1, the argument ``--version-comparison maven`` should be used as well as this option pack. It could not be included in the option pack due to complications with the version comparison option and its @@ -683,6 +683,7 @@ returns a page that looks something like this:: -a, --add-to INDEX Add to repo index INDEX -d, --search-directory DIR . Find degasolv cards here -I, --index-file FILE index.dsrepo The name of the repo file + -O, --index-sort-order ORDER descending May be 'ascending' or 'descending'. -V, --version-comparison CMP maven May be 'debian', 'maven', 'naive', 'python', 'rpm', 'rubygem', or 'semver'. -h, --help Print this help page @@ -739,6 +740,45 @@ Specify the Repo Index File Write the index file at the location ``FILE``. Default value is ``index.dsrepo``. It is good practice to use the default value. +.. _index-sort-order: + +Specify the Index Sort Order +**************************** + ++-----------------------------+---------------------------------------+ +| Short option | ``-O ORDER`` | ++-----------------------------+---------------------------------------+ +| Long option | ``--index-sort-order ORDER`` | ++-----------------------------+---------------------------------------+ +| EDN Config file key | ``:index-sort-order "ORDER"`` | ++-----------------------------+---------------------------------------+ +| JSON Config file key | ``"index-sort-order": "ORDER",`` | ++-----------------------------+---------------------------------------+ +| Version introduced | 2.1.0 | ++-----------------------------+---------------------------------------+ + +Specify that the packages within the index should be sorted by version number +in either ``descending`` or ``ascending`` order. This has a significant impact +on which version Degasolv chooses during dependency resolution. + +Degasolv "trusts" the index. The index lists versions packages under a +particular package name in a particular order, and Degasolv tries packages +according to the order found in the index. This means that if the list of +available package versions for any particular package name are sorted in +descending order by version, then Degasolv will try the latest versions first. +This is almost always what admins want in most dependency settings, and so has +been the default for Degasolv before version 2.1.0 . + +However, with the advent of golang's use of `Minimum Version Selection`_, a use +case has arisen for picking the smallest version first as part of resolution. + +As of version 2.1.0, specific performance enhancements (internally labelled +"version suggestion"), together with the option to specify an ``ascending`` +version index sort order, allows the admin to ask Degasolv to practice +minimum version selection. + +.. _Minimum Version Selection: https://research.swtch.com/vgo-mvs + .. _version-comparison-generate: Specify the Version Comparison Algorithm @@ -1613,7 +1653,7 @@ Specify a Package System +-----------------------------+---------------------------------------+ Specify package system to use. By default, this -value is ``degasolv``. This causes the Degasolv ``resolve-locations`` +value is ``degasolv``. This causes the Degasolv's ``resolve-locations`` command to behave normally. Other available values are shown below. diff --git a/docs/contributing.rst b/docs/contributing.rst index b0ec301..6ac5cd4 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -1,3 +1,6 @@ + +.. _Contributing Guide: + Contributing Guide ================== @@ -20,26 +23,36 @@ whether or not it is likely to be accepted: `git-flow`_ framework for branch management. Please make PRs to the ``develop`` branch. 2. **Do you have tests in your PR, and do they pass?** Tests are in - two places in degasolv: the ``test/degasolv`` directory, where more + two places in Degasolv: the ``test/degasolv`` directory, where more or less normal unit tests reside; and the ``test/resources/scripts`` directory, where scripty-integration - tests reside. You must have at least a script test as a - "spot-check" of your feature if the PR is to be merged. The test - need not be elaborate; simple tests are better than no tests. + tests reside. You must have at least a script test (and preferrably one or + more unit tests) as a "spot-check" of your feature if the PR is to be + merged. The test need not be elaborate; a simple test is better than no + tests. 3. **Is your PR backwards compatible?** The biggest feature Degasolv - provides is backwards compatibility. If Degasolv breaks a build, it - is a bug. A PR is herein defined to be "backwards incompatible" - if 1) it changes any previously merged unit or script test and 2) + provides is backwards compatibility. + + We only consider backwards incompatible changes + in the form of new options for the "correct" behavior and switching the + default for that option in a new version, ideally a major version. + + If Degasolv breaks a build, it is a bug. If it breaks a build in a way + that can't be fixed by configuration, it is a bad bug. + + A good test if a PR is "backwards compatible" + is if 1) it changes any previously merged script test and 2) if it breaks any of them. + 4. **Did you add documentation around the feature in your PR?** Generally this at least means adding something to the :ref:`Command Reference` document. 5. **Did you add an entry to the Changelog?** This project keeps a curated :ref:`changelog `. -There are some exceptions to the above rules. If your patch is less than -two lines' difference from the previous version, your PR may be a "typo" PR, -which may qualify to get around some of the above rules. Just ask the team -on your GitHub issue. +There are some exceptions to the above rules. For example, if your patch is +less than two lines' difference from the previous version, your PR may be a +"typo" PR, which may qualify to get around some of the above rules. Just ask +the team on your GitHub issue. .. _git-flow: http://nvie.com/posts/a-successful-git-branching-model/ diff --git a/docs/get-degasolv.rst b/docs/get-degasolv.rst index 49f133d..dfdf317 100644 --- a/docs/get-degasolv.rst +++ b/docs/get-degasolv.rst @@ -44,7 +44,7 @@ Degasolv lives out on `Github`_. Support & Problems ------------------ -If you have a hard time using degasolv to resolve dependencies within +If you have a hard time using Degasolv to resolve dependencies within builds, it is a bug! Please do not hesitate to let the authors know via `GitHub issue`_ :). @@ -59,6 +59,7 @@ You can also talk to us using `Gitter`_ or the `Google Group "degasolv-users"`_. Contributions ------------- -Please contribute to Degasolv! `Pull requests`_ are most welcome. +Please contribute to Degasolv! `Pull requests`_ are most welcome. Please +have a look at the :ref:`Contributing Guide` first. .. _Pull requests: https://github.com/djhaskin987/degasolv/pulls From aa14c464025a468b2b026d09b6932aadd6f2c530 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Thu, 31 Oct 2019 21:11:29 -0600 Subject: [PATCH 40/41] Bump version number to 2.1.0 --- project.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.clj b/project.clj index 68c5760..7952fcf 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject degasolv/degasolv "2.1.0-SNAPSHOT" +(defproject degasolv/degasolv "2.1.0" :description "Dependency tracker with an eye toward building and shipping software." :url "http://github.com/djhaskin987/degasolv" :license {:name "Eclipse Public License" From fbbb7099cf12eb58ea8e01dee3596f4faeea07c4 Mon Sep 17 00:00:00 2001 From: Daniel Jay Haskin Date: Thu, 31 Oct 2019 21:18:07 -0600 Subject: [PATCH 41/41] Try to fix the build --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2fc2054..9348ae4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -152,7 +152,7 @@ jobs: test_centos7_package: docker: - - image: djhaskin987/test-centos-installer:centos7 + - image: djhaskin987/test-centos-installers:centos7 version: 2 steps: - attach_workspace: @@ -164,7 +164,7 @@ jobs: test_centos8_package: docker: - - image: djhaskin987/test-centos-installer:centos8 + - image: djhaskin987/test-centos-installers:centos8 version: 2 steps: - attach_workspace: