Browse Source

Transition to using JSON5 for package manifests

default_compile_flags
vector-of-bool 4 years ago
parent
commit
9f82212bdc
39 changed files with 328 additions and 125 deletions
  1. +9
    -0
      catalog.json
  2. +5
    -5
      docs/err/dup-lib-name.rst
  3. +1
    -1
      docs/err/invalid-pkg-filesystem.rst
  4. +9
    -0
      docs/err/invalid-pkg-manifest.rst
  5. +1
    -1
      docs/err/unknown-usage.rst
  6. +7
    -7
      docs/guide/catalog.rst
  7. +39
    -31
      docs/guide/interdeps.rst
  8. +12
    -10
      docs/guide/packages.rst
  9. +1
    -1
      docs/guide/repo.rst
  10. +8
    -8
      docs/tut/hello-test.rst
  11. +9
    -8
      docs/tut/hello-world.rst
  12. +1
    -0
      library.dds
  13. +1
    -0
      package.dds
  14. +17
    -0
      package.json5
  15. +1
    -1
      src/dds.main.cpp
  16. +10
    -4
      src/dds/catalog/get.cpp
  17. +20
    -6
      src/dds/error/errors.cpp
  18. +1
    -0
      src/dds/error/errors.hpp
  19. +97
    -2
      src/dds/package/manifest.cpp
  20. +2
    -1
      src/dds/package/manifest.hpp
  21. +21
    -7
      src/dds/source/dist.cpp
  22. +5
    -3
      tests/basics/test_basics.py
  23. +6
    -2
      tests/catalog/get_test.py
  24. +1
    -1
      tests/deps/git-remote/catalog.json
  25. +0
    -5
      tests/deps/git-remote/package.dds
  26. +8
    -0
      tests/deps/git-remote/package.json5
  27. +0
    -2
      tests/deps/no-deps/package.dds
  28. +4
    -0
      tests/deps/no-deps/package.json5
  29. +0
    -4
      tests/deps/use-remote/package.dds
  30. +7
    -0
      tests/deps/use-remote/package.json5
  31. +0
    -4
      tests/deps/use-spdlog/project/package.dds
  32. +7
    -0
      tests/deps/use-spdlog/project/package.json5
  33. +0
    -2
      tests/sdist/create/package.dds
  34. +4
    -0
      tests/sdist/create/package.json5
  35. +0
    -4
      tests/test_drivers/catch/custom-runner/package.dds
  36. +5
    -0
      tests/test_drivers/catch/custom-runner/package.json5
  37. +0
    -4
      tests/test_drivers/catch/main/package.dds
  38. +5
    -0
      tests/test_drivers/catch/main/package.json5
  39. +4
    -1
      tools/gen-catalog-json.py

+ 9
- 0
catalog.json View File

"ref": "0.1.0", "ref": "0.1.0",
"url": "https://github.com/vector-of-bool/json5.git" "url": "https://github.com/vector-of-bool/json5.git"
} }
},
"0.1.2": {
"depends": {},
"description": "A C++ implementation of a JSON5 parser",
"git": {
"auto-lib": null,
"ref": "0.1.2",
"url": "https://github.com/vector-of-bool/json5.git"
}
} }
}, },
"ms-wil": { "ms-wil": {

+ 5
- 5
docs/err/dup-lib-name.rst View File

The "namespace" of a library in this case is arbitrary and not necessarily The "namespace" of a library in this case is arbitrary and not necessarily
associated with any C++ ``namespace``. associated with any C++ ``namespace``.


If more than one library declares itself to have the same ``Name`` and lives in
the same ``Namespace``, ``dds`` will issue an error.
If more than one library declares itself to have the same ``name`` and lives in
the same ``namespace``, ``dds`` will issue an error.


To avoid this error in your own project and to avoid causing this error in your To avoid this error in your own project and to avoid causing this error in your
downstream consumers, the ``Namespace`` of your package should be considered
carefully and be unique. Do not use a ``Namespace`` that is likely to be used
downstream consumers, the ``namespace`` of your package should be considered
carefully and be unique. Do not use a ``namespace`` that is likely to be used
by another developer or organization, especially generic names. by another developer or organization, especially generic names.


If you are seeing this issue and it names a library that you do not own, it If you are seeing this issue and it names a library that you do not own, it
means that two or more of your dependencies are attempting to declare a library means that two or more of your dependencies are attempting to declare a library
of the same ``Name`` in the same ``Namespace``. This issue should be raised
of the same ``name`` in the same ``namespace``. This issue should be raised
with the maintainers of the packages in question. with the maintainers of the packages in question.


.. seealso:: .. seealso::

+ 1
- 1
docs/err/invalid-pkg-filesystem.rst View File

and is thoroughly explained on the :doc:`/guide/packages` page. and is thoroughly explained on the :doc:`/guide/packages` page.


For exporting/generating a source distribution from a package, the *package For exporting/generating a source distribution from a package, the *package
root* requires a ``package.dds`` file and each *library root* requires a
root* requires a ``package.json5`` file and each *library root* requires a
``library.dds`` file. ``library.dds`` file.


.. . .. .

+ 9
- 0
docs/err/invalid-pkg-manifest.rst View File

Error: Invalid package manifest
###############################

Every ``dds`` package must contain a valid package manifest, which is stored in
JSON5 format in ``package.json5`` (or similarly named file).

The contents of this file must follow a prescribed content, or ``dds`` will
reject the manifest. Refer to the :ref:`pkgs.pkgs` documentation page for more
information about how to declare packages.

+ 1
- 1
docs/err/unknown-usage.rst View File

A library can declare that it *uses* or *links* to another library by using the A library can declare that it *uses* or *links* to another library by using the
``Uses`` and ``Links`` keys in ``library.dds``, respectively. ``Uses`` and ``Links`` keys in ``library.dds``, respectively.


These requirements are specified by using the ``Namespace/Name`` pair that
These requirements are specified by using the ``namespace/name`` pair that
identifies a library. These are defined by both the project's dependencies and identifies a library. These are defined by both the project's dependencies and
the project itself. If a ``Uses`` or ``Links`` key does not correspond to a the project itself. If a ``Uses`` or ``Links`` key does not correspond to a
known library, ``dds`` will not be able to resolve the usage requirements, and known library, ``dds`` will not be able to resolve the usage requirements, and

+ 7
- 7
docs/guide/catalog.rst View File

dds catalog add <package-id> dds catalog add <package-id>
[--depends <requirement> [--depends <requirement> [...]]] [--depends <requirement> [--depends <requirement> [...]]]
[--git-url <url> --git-ref <ref>] [--git-url <url> --git-ref <ref>]
[--auto-lib <Namespace>/<Name>]
[--auto-lib <namespace>/<name>]


The ``<package-id>`` positional arguments is the ``name@version`` package ID The ``<package-id>`` positional arguments is the ``name@version`` package ID
that will be added to the catalog. The following options are supported: that will be added to the catalog. The following options are supported:
``--depends <requirement>`` ``--depends <requirement>``
This argument, which can be specified multiple times to represent multiple This argument, which can be specified multiple times to represent multiple
dependencies, sets the dependencies of the package within the catalog. If dependencies, sets the dependencies of the package within the catalog. If
the obtained package root contains a ``package.dds``, then the dependencies
listed here must be identical to those listed in ``package.dds``, or
dependency resolution may yield unexpected results.
the obtained package root contains a ``package.json5``, then the
dependencies listed here must be identical to those listed in
``package.json5``, or dependency resolution may yield unexpected results.


``--git-url <url>`` ``--git-url <url>``
Specify a Git URL to clone from to obtain the package. The root of the Specify a Git URL to clone from to obtain the package. The root of the
cloned repository must be a package root, but does not necessarily need to cloned repository must be a package root, but does not necessarily need to
have the ``package.dds`` and ``library.dds`` files if relying on the
have the ``package.json5`` and ``library.dds`` files if relying on the
``--auto-lib`` parameter. ``--auto-lib`` parameter.


``--git-ref`` **must** be passed with ``--git-url``. ``--git-ref`` **must** be passed with ``--git-url``.
can only be specified for packages that contain a single library root at can only be specified for packages that contain a single library root at
the package root. the package root.


The form of the argument is that of ``<Namespapce>/<Name>``, where
``Namespace`` and ``Name`` are the usage requirement keys that should be
The form of the argument is that of ``<namespace>/<name>``, where
``namespace`` and ``name`` are the usage requirement keys that should be
generated for the library. generated for the library.





+ 39
- 31
docs/guide/interdeps.rst View File

******************** ********************


Consider that we are creating a package ``acme-gadgets@4.3.6``. We declare the Consider that we are creating a package ``acme-gadgets@4.3.6``. We declare the
name and version in the ``package.dds`` in the package root:
name and version in the ``package.json5`` in the package root:


.. code-block::
.. code-block:: js


Name: acme-gadgets
Version: 4.3.6
Namespace: acme
{
name: 'acme-widgets',
version: '4.3.6',
namespace: 'acme',
}


.. note:: .. note::
The ``Namespace`` field is required, but will be addressed in the
The ``namespace`` field is required, but will be addressed in the
:ref:`deps.lib-deps` section. :ref:`deps.lib-deps` section.


Suppose that our package's libraries build upon the libraries in the Suppose that our package's libraries build upon the libraries in the
not as new as ``2.0.0``. Such a dependency can be declared with the ``Depends`` not as new as ``2.0.0``. Such a dependency can be declared with the ``Depends``
key: key:


.. code-block::
:emphasize-lines: 5

Name: acme-gadgets
Version: 4.3.6
Namespace: acme
.. code-block:: js
:emphasize-lines: 5-7


Depends: acme-widgets ^1.4.3
{
name: 'acme-gadgets',
version: '4.3.6',
namespace: 'acme',
depends: {
'acme-widgets': '^1.4.3',
},
}


.. seealso:: :ref:`deps.ranges`. .. seealso:: :ref:`deps.ranges`.


additional ``Depends`` keys additional ``Depends`` keys


.. code-block:: .. code-block::
:emphasize-lines: 5-7

Name: acme-gadgets
Version: 4.3.6
Namespace: acme

Depends: acme-widgets ^1.4.3
Depends: acme-gizmos ~5.6.5
Depends: acme-utils ^3.3.0
:emphasize-lines: 7-8

{
name: 'acme-gadgets',
version: '4.3.6',
namespace: 'acme',
depends: {
'acme-widgets': '^1.4.3',
'acme-gizmos': '~5.6.5',
'acme-utils': '^3.3.0',
},
}


When ``dds`` attempts to build a project, it will first build the dependency When ``dds`` attempts to build a project, it will first build the dependency
solution by iteratively scanning the dependencies of the containing project and solution by iteratively scanning the dependencies of the containing project and
To announce that a library wishes to *use* another library, use the aptly-named To announce that a library wishes to *use* another library, use the aptly-named
``Uses`` key: ``Uses`` key:


.. code-block::
.. code-block:: js
:emphasize-lines: 3-5 :emphasize-lines: 3-5


Name: gadgets Name: gadgets
Uses: acme/gizmos Uses: acme/gizmos
Uses: acme/utils Uses: acme/utils


Here is where the package's ``Namespace`` key comes into play: A library's
qualified name is specified by joining the ``Namespace`` of the containing
package with the ``Name`` of the library within that package with a ``/``
Here is where the package's ``namespace`` key comes into play: A library's
qualified name is specified by joining the ``namespace`` of the containing
package with the ``name`` of the library within that package with a ``/``
between them. between them.


It is the responsibility of package authors to document the ``Namespace`` and
It is the responsibility of package authors to document the ``namespace`` and
``Name`` of the packages and libraries that they distribute. ``Name`` of the packages and libraries that they distribute.


.. note:: .. note::
The ``Namespace`` of a package is completely arbitrary, and need not relate
The ``namespace`` of a package is completely arbitrary, and need not relate
to a C++ ``namespace``. to a C++ ``namespace``.


.. note:: .. note::
The ``Namespace`` need not be unique to a single package. For example, a
single organization (Like Acme Inc.) can share a single ``Namespace`` for
The ``namespace`` need not be unique to a single package. For example, a
single organization (Like Acme Inc.) can share a single ``namespace`` for
many of their packages and libraries. many of their packages and libraries.


However, it is essential that the ``<Namespace>/<Name>`` pair be
However, it is essential that the ``<namespace>/<name>`` pair be
universally unique, so choose wisely! universally unique, so choose wisely!


Once the ``Uses`` key appears in the ``library.dds`` file of a library, ``dds`` Once the ``Uses`` key appears in the ``library.dds`` file of a library, ``dds``

+ 12
- 10
docs/guide/packages.rst View File

within a repository or package catalog. within a repository or package catalog.


In order for a package to be exported by ``dds`` it must have a In order for a package to be exported by ``dds`` it must have a
``package.dds`` file at its package root. Three keys are required to be
present in the ``package.dds`` file: ``Name``, ``Version``, and ``Namespace``:
``package.json5`` file at its package root. Three keys are required to be
present in the ``package.json5`` file: ``name``, ``version``, and ``namespace``:


.. code-block:: yaml
.. code-block:: js


Name: acme-widgets
Version: 6.7.3
Namespace: acme
{
name: 'acme-widgets',
version: '6.7.3',
namespace: 'acme',
}


``Version`` must be a valid semantic version string.
``version`` must be a valid semantic version string.


.. note:: .. note::
The ``Namespace`` key is arbitrary, and not necessarily associated with
and C++ ``namespace``.
The ``namespace`` key is arbitrary, and not necessarily associated with
any C++ ``namespace``.


.. seealso:: .. seealso::
The purpose of ``Namespace``, as well as additional options in this file,
The purpose of ``namespace``, as well as additional options in this file,
are described in the :ref:`deps.pkg-deps` page are described in the :ref:`deps.pkg-deps` page





+ 1
- 1
docs/guide/repo.rst View File

include/ include/
src/ src/
library.dds library.dds
package.dds
package.json5




.. _repo.export-local: .. _repo.export-local:

+ 8
- 8
docs/tut/hello-test.rst View File

.. _catch2: https://github.com/catchorg/Catch2 .. _catch2: https://github.com/catchorg/Catch2


To make use of Catch as our test driver, we simply declare this intent in the To make use of Catch as our test driver, we simply declare this intent in the
``package.dds`` file at the package root:
``package.json5`` file at the package root:


.. code-block:: yaml
:caption: ``<root>/package.dds``
.. code-block:: js
:caption: ``<root>/package.json5``
:emphasize-lines: 5 :emphasize-lines: 5


Name: hello-dds
Version: 0.1.0
Namespace: tutorial
Test-Driver: Catch-Main
{
name: 'hello-dds',
version: '0.1.0',
namespace: 'tutorial',
}


If you now run ``dds build``, we will get a linker error for a multiply-defined If you now run ``dds build``, we will get a linker error for a multiply-defined
``main`` function. When setting the ``Test-Driver`` to ``Catch-Main``, ``dds`` ``main`` function. When setting the ``Test-Driver`` to ``Catch-Main``, ``dds``

+ 9
- 8
docs/tut/hello-world.rst View File



``dds`` will work happily with packages that do not declare themselves, as long ``dds`` will work happily with packages that do not declare themselves, as long
as the filesystem structure is sufficient. However: To use features covered in as the filesystem structure is sufficient. However: To use features covered in
later tutorials, we'll need a simple ``package.dds`` file to declare
later tutorials, we'll need a simple ``package.json5`` file to declare
information about are package. This file should be placed directly in the information about are package. This file should be placed directly in the
package root: package root:


.. code-block:: yaml
:caption: ``<root>/package.dds``

Name: hello-dds
Version: 0.1.0
Namespace: tutorial
.. code-block:: js
:caption: ``<root>/package.json5``


{
name: 'hello-dds',
version: '0.1.0',
namespace: 'tutorial',
}


.. note:: .. note::
The ``Namespace`` option will be discussed later.
The ``namespace`` option will be discussed later.


Rebuilding the project will show no difference at the moment. Rebuilding the project will show no difference at the moment.



+ 1
- 0
library.dds View File

Uses: neo/fun Uses: neo/fun
Uses: semver/semver Uses: semver/semver
Uses: pubgrub/pubgrub Uses: pubgrub/pubgrub
Uses: vob/json5

+ 1
- 0
package.dds View File

Depends: neo-fun 0.1.0 Depends: neo-fun 0.1.0
Depends: semver 0.2.1 Depends: semver 0.2.1
Depends: pubgrub 0.2.0 Depends: pubgrub 0.2.0
Depends: json5 0.1.2


Test-Driver: Catch-Main Test-Driver: Catch-Main

+ 17
- 0
package.json5 View File

{
"$schema": "what",
name: 'dds',
version: '0.1.0',
depends: {
spdlog: '1.4.2',
'ms-wil': '2019.11.10',
'range-v3': '0.10.0',
'nlohmann-json': '3.7.1',
'neo-sqlite3': '0.2.2',
'neo-fun': '0.1.0',
'semver': '0.2.1',
pubgrub: '0.2.0',
json5: '0.1.2',
},
test_driver: 'Catch-Main',
}

+ 1
- 1
src/dds.main.cpp View File

params.toolchain = tc_filepath.get_toolchain(); params.toolchain = tc_filepath.get_toolchain();
params.parallel_jobs = n_jobs.Get(); params.parallel_jobs = n_jobs.Get();
dds::package_manifest man; dds::package_manifest man;
const auto man_filepath = project.root.Get() / "package.dds";
const auto man_filepath = project.root.Get() / "package.json5";
if (exists(man_filepath)) { if (exists(man_filepath)) {
man = dds::package_manifest::load_from_file(man_filepath); man = dds::package_manifest::load_from_file(man_filepath);
} }

+ 10
- 4
src/dds/catalog/get.cpp View File

#include <dds/error/errors.hpp> #include <dds/error/errors.hpp>
#include <dds/proc.hpp> #include <dds/proc.hpp>


#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>


using namespace dds; using namespace dds;
spdlog::info("Create sdist from clone ..."); spdlog::info("Create sdist from clone ...");
if (git.auto_lib.has_value()) { if (git.auto_lib.has_value()) {
spdlog::info("Generating library data automatically"); spdlog::info("Generating library data automatically");
auto pkg_strm = dds::open(tmpdir.path() / "package.dds", std::ios::binary | std::ios::out);
pkg_strm << "Name: " << listing.ident.name << '\n' //
<< "Version: " << listing.ident.version.to_string() << '\n' //
<< "Namespace: " << git.auto_lib->namespace_;

auto pkg_strm
= dds::open(tmpdir.path() / "package.json5", std::ios::binary | std::ios::out);
auto man_json = nlohmann::json::object();
man_json["name"] = listing.ident.name;
man_json["version"] = listing.ident.version.to_string();
man_json["namespace"] = git.auto_lib->namespace_;
pkg_strm << nlohmann::to_string(man_json);

auto lib_strm = dds::open(tmpdir.path() / "library.dds", std::ios::binary | std::ios::out); auto lib_strm = dds::open(tmpdir.path() / "library.dds", std::ios::binary | std::ios::out);
lib_strm << "Name: " << git.auto_lib->name; lib_strm << "Name: " << git.auto_lib->name;
} }

+ 20
- 6
src/dds/error/errors.cpp View File

return "sdist-ident-mismatch.html"; return "sdist-ident-mismatch.html";
case errc::corrupted_build_db: case errc::corrupted_build_db:
return "corrupted-build-db.html"; return "corrupted-build-db.html";
case errc::invalid_pkg_manifest:
return "invalid-pkg-manifest.html";
case errc::invalid_version_range_string: case errc::invalid_version_range_string:
return "invalid-version-string.html#range"; return "invalid-version-string.html#range";
case errc::invalid_version_string: case errc::invalid_version_string:
The catalog database schema doesn't match what dds expects. This indicates that The catalog database schema doesn't match what dds expects. This indicates that
the database file has been modified in a way that dds cannot automatically fix the database file has been modified in a way that dds cannot automatically fix
and handle. and handle.
)";
case errc::invalid_pkg_manifest:
return R"(
The package manifest is malformed. Refer to the documentation and above error
message for more details.
)"; )";
case errc::invalid_catalog_json: case errc::invalid_catalog_json:
return R"( return R"(
return R"( return R"(
A `Uses` or `Links` field for a library specifies a library of an unknown name. A `Uses` or `Links` field for a library specifies a library of an unknown name.
Check your spelling, and check that the package containing the library is Check your spelling, and check that the package containing the library is
available, either from the `package.dds` or from the `INDEX.lmi` that was used
available, either from the `package.json5` or from the `INDEX.lmi` that was used
for the build. for the build.
)"; )";
case errc::none: case errc::none:
"that was expected of it"; "that was expected of it";
case errc::corrupted_build_db: case errc::corrupted_build_db:
return "The build database file is corrupted"; return "The build database file is corrupted";
case errc::invalid_pkg_manifest:
return "The package manifest is invalid";
case errc::invalid_version_range_string: case errc::invalid_version_range_string:
return "Attempted to parse an invalid version range string. <- (Seeing this text is a " return "Attempted to parse an invalid version range string. <- (Seeing this text is a "
"`dds` bug. Please report it.)"; "`dds` bug. Please report it.)";
case errc::invalid_version_string: case errc::invalid_version_string:
return "Attempted to parse an invalid version string. <- (Seeing this text is a `dds` bug. "
return "Attempted to parse an invalid version string. <- (Seeing this text is a `dds` "
"bug. "
"Please report it.)"; "Please report it.)";
case errc::invalid_config_key: case errc::invalid_config_key:
return "Found an invalid configuration key. <- (Seeing this text is a `dds` bug. Please "
return "Found an invalid configuration key. <- (Seeing this text is a `dds` bug. "
"Please "
"report it.)"; "report it.)";
case errc::invalid_lib_filesystem: case errc::invalid_lib_filesystem:
case errc::invalid_pkg_filesystem: case errc::invalid_pkg_filesystem:
return "The filesystem structure of the package/library is invalid. <- (Seeing this text "
return "The filesystem structure of the package/library is invalid. <- (Seeing this "
"text "
"is a `dds` bug. Please report it.)"; "is a `dds` bug. Please report it.)";
case errc::invalid_pkg_id: case errc::invalid_pkg_id:
return "A package identifier is invalid <- (Seeing this text is a `dds` bug. Please " return "A package identifier is invalid <- (Seeing this text is a `dds` bug. Please "
"report it.)"; "report it.)";
case errc::invalid_pkg_name: case errc::invalid_pkg_name:
return "A package name is invalid <- (Seeing this text is a `dds` bug. Please report it.)";
return "A package name is invalid <- (Seeing this text is a `dds` bug. Please report "
"it.)";
case errc::sdist_exists: case errc::sdist_exists:
return "The source ditsribution already exists at the destination <- (Seeing this text is "
return "The source ditsribution already exists at the destination <- (Seeing this "
"text is "
"a `dds` bug. Please report it.)"; "a `dds` bug. Please report it.)";
case errc::unknown_test_driver: case errc::unknown_test_driver:
return "The specified Test-Driver is not known to `dds`"; return "The specified Test-Driver is not known to `dds`";

+ 1
- 0
src/dds/error/errors.hpp View File



corrupted_build_db, corrupted_build_db,


invalid_pkg_manifest,
invalid_version_range_string, invalid_version_range_string,
invalid_version_string, invalid_version_string,
invalid_pkg_id, invalid_pkg_id,

+ 97
- 2
src/dds/package/manifest.cpp View File

#include <range/v3/view/split.hpp> #include <range/v3/view/split.hpp>
#include <range/v3/view/split_when.hpp> #include <range/v3/view/split_when.hpp>
#include <range/v3/view/transform.hpp> #include <range/v3/view/transform.hpp>
#include <spdlog/fmt/fmt.h>
#include <spdlog/spdlog.h>

#include <json5/parse_data.hpp>


using namespace dds; using namespace dds;


package_manifest package_manifest::load_from_file(const fs::path& fpath) {
package_manifest package_manifest::load_from_dds_file(const fs::path& fpath) {
spdlog::warn(
"Using deprecated package.dds parsing (on file {}). This will be removed soon. Migrate!",
fpath.string());
auto kvs = lm::parse_file(fpath); auto kvs = lm::parse_file(fpath);
package_manifest ret; package_manifest ret;
std::string version_str; std::string version_str;


return ret; return ret;
} }

package_manifest package_manifest::load_from_file(const fs::path& fpath) {
auto content = slurp_file(fpath);
auto data = json5::parse_data(content);

if (!data.is_object()) {
throw_user_error<errc::invalid_pkg_manifest>("Root value must be an object");
}

const auto& obj = data.as_object();
package_manifest ret;

/// Get the name
auto it = obj.find("name");
if (it == obj.end() || !it->second.is_string() || it->second.as_string().empty()) {
throw_user_error<errc::invalid_pkg_name>("'name' field in [{}] must be a non-empty string",
fpath.string());
}
ret.namespace_ = ret.pkg_id.name = it->second.as_string();

/// Get the version
it = obj.find("version");
if (it == obj.end() || !it->second.is_string()) {
throw_user_error<
errc::invalid_version_string>("'version' field in [{}] must be a version string",
fpath.string());
}
auto version_str = it->second.as_string();
ret.pkg_id.version = semver::version::parse(version_str);

/// Get the namespace
it = obj.find("namespace");
if (it != obj.end()) {
if (!it->second.is_string() || it->second.as_string().empty()) {
throw_user_error<errc::invalid_pkg_manifest>(
"'namespace' attribute in [{}] must be a non-empty string", fpath.string());
}
ret.namespace_ = it->second.as_string();
}

/// Get the test driver
it = obj.find("test_driver");
if (it != obj.end()) {
if (!it->second.is_string()) {
throw_user_error<errc::invalid_pkg_manifest>(
"'test_driver' attribute in [{}] must be a non-empty string", fpath.string());
}
auto& test_driver_str = it->second.as_string();
if (test_driver_str == "Catch-Main") {
ret.test_driver = test_lib::catch_main;
} else if (test_driver_str == "Catch") {
ret.test_driver = test_lib::catch_;
} else {
auto dym = *did_you_mean(test_driver_str, {"Catch-Main", "Catch"});
throw_user_error<
errc::unknown_test_driver>("Unknown 'Test-Driver' '{}' (Did you mean '{}'?)",
test_driver_str,
dym);
}
}

/// Get the dependencies
it = obj.find("depends");
if (it != obj.end()) {
if (!it->second.is_object()) {
throw_user_error<errc::invalid_pkg_manifest>(
"'depends' field must be an object mapping package name to version ranges");
}

for (const auto& [pkg_name, range_str_] : it->second.as_object()) {
if (!range_str_.is_string()) {
throw_user_error<
errc::invalid_pkg_manifest>("Dependency for '{}' must be a range string",
pkg_name);
}
try {
auto rng = semver::range::parse_restricted(range_str_.as_string());
dependency dep{pkg_name, {rng.low(), rng.high()}};
ret.dependencies.push_back(std::move(dep));
} catch (const semver::invalid_range&) {
throw_user_error<errc::invalid_version_range_string>(
"Invalid version range string '{}' in dependency declaration for '{}'",
range_str_.as_string(),
pkg_name);
}
}
}

return ret;
}

+ 2
- 1
src/dds/package/manifest.hpp View File

namespace dds { namespace dds {


/** /**
* Possible values for Test-Driver in a package.dds
* Possible values for test_driver in a package.json5
*/ */
enum class test_lib { enum class test_lib {
catch_, catch_,
* Load a package manifest from a file on disk. * Load a package manifest from a file on disk.
*/ */
static package_manifest load_from_file(path_ref); static package_manifest load_from_file(path_ref);
static package_manifest load_from_dds_file(path_ref);
}; };


} // namespace dds } // namespace dds

+ 21
- 7
src/dds/source/dist.cpp View File

sdist_copy_library(out, lib, params); sdist_copy_library(out, lib, params);
} }


auto man_path = params.project_dir / "package.dds";
if (!fs::is_regular_file(man_path)) {
auto j5_man_path = params.project_dir / "package.json5";
auto dds_man_path = params.project_dir / "package.dds";
package_manifest pkg_man;

if (fs::is_regular_file(j5_man_path)) {
pkg_man = package_manifest::load_from_file(j5_man_path);
sdist_export_file(out, params.project_dir, j5_man_path);
} else if (fs::is_regular_file(dds_man_path)) {
pkg_man = package_manifest::load_from_dds_file(dds_man_path);
sdist_export_file(out, params.project_dir, dds_man_path);
} else {
throw_user_error<errc::invalid_pkg_filesystem>( throw_user_error<errc::invalid_pkg_filesystem>(
"Creating a source distribution requires a package.dds file for the project (Expected "
"Creating a source distribution requires a package.json5 file for the project "
"(Expected "
"[{}])", "[{}])",
man_path.string());
j5_man_path.string());
} }
sdist_export_file(out, params.project_dir, man_path);
auto pkg_man = package_manifest::load_from_file(man_path);


spdlog::info("Generated export as {}", pkg_man.pkg_id.to_string()); spdlog::info("Generated export as {}", pkg_man.pkg_id.to_string());


} }


sdist sdist::from_directory(path_ref where) { sdist sdist::from_directory(path_ref where) {
auto pkg_man = package_manifest::load_from_file(where / "package.dds");
/// XXX: Remove this logic once package.dds is all gone.
auto j5_path = where / "package.json5";
auto dds_path = where / "package.dds";

// Load based on whichever is actually present
auto pkg_man = fs::is_regular_file(j5_path) ? package_manifest::load_from_file(j5_path)
: package_manifest::load_from_dds_file(dds_path);
return sdist{std::move(pkg_man), where}; return sdist{std::move(pkg_man), where};
} }

+ 5
- 3
tests/basics/test_basics.py View File



def basic_pkg_dds(dds: DDS): def basic_pkg_dds(dds: DDS):
return set_contents( return set_contents(
dds.source_root / 'package.dds', b'''
Name: test-pkg
Version: 0.2.2
dds.source_root / 'package.json5', b'''
{
name: 'test-pkg',
version: '0.2.2',
}
''') ''')





+ 6
- 2
tests/catalog/get_test.py View File

from tests import dds, DDS from tests import dds, DDS
from tests.fileutil import ensure_dir from tests.fileutil import ensure_dir


import pytest



def test_get(dds: DDS): def test_get(dds: DDS):
dds.scope.enter_context(ensure_dir(dds.build_dir)) dds.scope.enter_context(ensure_dir(dds.build_dir))
'0.2.2': { '0.2.2': {
'depends': {}, 'depends': {},
'git': { 'git': {
'url': 'https://github.com/vector-of-bool/neo-sqlite3.git',
'ref': '0.2.2',
'url':
'https://github.com/vector-of-bool/neo-sqlite3.git',
'ref':
'0.2.2',
}, },
}, },
}, },

+ 1
- 1
tests/deps/git-remote/catalog.json View File

"0.1.0": { "0.1.0": {
"git": { "git": {
"url": "https://github.com/vector-of-bool/neo-buffer.git", "url": "https://github.com/vector-of-bool/neo-buffer.git",
"ref": "develop"
"ref": "0.1.0"
}, },
"depends": {} "depends": {}
} }

+ 0
- 5
tests/deps/git-remote/package.dds View File

Name: deps-test
Version: 0.0.0

Depends: neo-buffer 0.1.0
Depends: range-v3 0.9.1

+ 8
- 0
tests/deps/git-remote/package.json5 View File

{
name: 'deps-test',
version: '0.0.0',
depends: {
'neo-buffer': '0.1.0',
'range-v3': '0.9.1',
}
}

+ 0
- 2
tests/deps/no-deps/package.dds View File

Name: deps-test
Version: 0.0.0

+ 4
- 0
tests/deps/no-deps/package.json5 View File

{
name: 'deps-test',
version: '0.0.0'
}

+ 0
- 4
tests/deps/use-remote/package.dds View File

Name: json-test
Version: 0.0.0

Depends: nlohmann-json 3.7.1

+ 7
- 0
tests/deps/use-remote/package.json5 View File

{
"name": "json-test",
"version": "0.0.0",
"depends": {
"nlohmann-json": "3.7.1"
}
}

+ 0
- 4
tests/deps/use-spdlog/project/package.dds View File

Name: test
Version: 0.0.0

Depends: spdlog 1.4.2

+ 7
- 0
tests/deps/use-spdlog/project/package.json5 View File

{
name: 'test',
version: '0.0.0',
depends: {
'spdlog': '1.4.2',
},
}

+ 0
- 2
tests/sdist/create/package.dds View File

Name: foo
Version: 1.2.3

+ 4
- 0
tests/sdist/create/package.json5 View File

{
name: 'foo',
version: '1.2.3',
}

+ 0
- 4
tests/test_drivers/catch/custom-runner/package.dds View File

Name: Test
Version: 0.0.0

Test-Driver: Catch

+ 5
- 0
tests/test_drivers/catch/custom-runner/package.json5 View File

{
"name": "test",
"version": "0.0.0",
"test_driver": "Catch",
}

+ 0
- 4
tests/test_drivers/catch/main/package.dds View File

Name: Test
Version: 0.0.0

Test-Driver: Catch-Main

+ 5
- 0
tests/test_drivers/catch/main/package.json5 View File

{
"name": "test",
"version": "0.0.0",
"test_driver": "Catch-Main",
}

+ 4
- 1
tools/gen-catalog-json.py View File

), ),
many_versions( many_versions(
'json5', 'json5',
('0.1.0', ),
(
'0.1.0',
'0.1.2',
),
description='A C++ implementation of a JSON5 parser', description='A C++ implementation of a JSON5 parser',
git_url='https://github.com/vector-of-bool/json5.git', git_url='https://github.com/vector-of-bool/json5.git',
), ),

Loading…
Cancel
Save