Basic version working.
This commit is contained in:
		
							parent
							
								
									fd93a937a4
								
							
						
					
					
						commit
						d9d0929bb7
					
				| 
						 | 
				
			
			@ -1,5 +1,12 @@
 | 
			
		|||
<component name="ProjectCodeStyleConfiguration">
 | 
			
		||||
  <code_scheme name="Project" version="173">
 | 
			
		||||
    <option name="OTHER_INDENT_OPTIONS">
 | 
			
		||||
      <value>
 | 
			
		||||
        <option name="INDENT_SIZE" value="8" />
 | 
			
		||||
        <option name="TAB_SIZE" value="8" />
 | 
			
		||||
        <option name="USE_TAB_CHARACTER" value="true" />
 | 
			
		||||
      </value>
 | 
			
		||||
    </option>
 | 
			
		||||
    <Objective-C>
 | 
			
		||||
      <option name="INDENT_NAMESPACE_MEMBERS" value="0" />
 | 
			
		||||
      <option name="INDENT_C_STRUCT_MEMBERS" value="8" />
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +30,13 @@
 | 
			
		|||
        <pair source="c++m" header="" fileNamingConvention="NONE" />
 | 
			
		||||
      </extensions>
 | 
			
		||||
    </files>
 | 
			
		||||
    <codeStyleSettings language="Markdown">
 | 
			
		||||
      <indentOptions>
 | 
			
		||||
        <option name="INDENT_SIZE" value="8" />
 | 
			
		||||
        <option name="TAB_SIZE" value="8" />
 | 
			
		||||
        <option name="USE_TAB_CHARACTER" value="true" />
 | 
			
		||||
      </indentOptions>
 | 
			
		||||
    </codeStyleSettings>
 | 
			
		||||
    <codeStyleSettings language="ObjectiveC">
 | 
			
		||||
      <option name="BLANK_LINES_BEFORE_IMPORTS" value="2" />
 | 
			
		||||
      <option name="BLANK_LINES_AFTER_IMPORTS" value="2" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,8 +44,16 @@ else ()
 | 
			
		|||
endif ()
 | 
			
		||||
add_compile_definitions(SCSL_DESKTOP_BUILD)
 | 
			
		||||
 | 
			
		||||
set(HEADERS)
 | 
			
		||||
set(SOURCES)
 | 
			
		||||
set(HEADERS
 | 
			
		||||
		include/Debian.h
 | 
			
		||||
		include/Utility.h
 | 
			
		||||
		include/Generic.h
 | 
			
		||||
)
 | 
			
		||||
set(SOURCES
 | 
			
		||||
		src/Debian.cc
 | 
			
		||||
		src/Utility.cc
 | 
			
		||||
		src/Generic.cc
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
include_directories(SYSTEM include)
 | 
			
		||||
include_directories(SYSTEM ${CURLPP_INCLUDE_DIRS})
 | 
			
		||||
| 
						 | 
				
			
			@ -57,6 +65,6 @@ target_link_libraries(${PROJECT_NAME}-packager ${SCSL_LIBRARIES} ${CURLPP_LIBRAR
 | 
			
		|||
 | 
			
		||||
### INCLUDES ###
 | 
			
		||||
 | 
			
		||||
#include(cmake/docs.cmake)
 | 
			
		||||
#include(cmake/install.cmake)
 | 
			
		||||
#include(cmake/packaging.cmake)
 | 
			
		||||
include(cmake/docs.cmake)
 | 
			
		||||
include(cmake/install.cmake)
 | 
			
		||||
include(cmake/packaging.cmake)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,6 @@ add_custom_target(manpages)
 | 
			
		|||
### Generate man pages from markdown ###
 | 
			
		||||
 | 
			
		||||
# md2man uses scdoc to produce a man page from a markdown document.
 | 
			
		||||
if (LINUX and not DISABLE_SCDOC)
 | 
			
		||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man
 | 
			
		||||
	DESTINATION share)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,34 +19,33 @@ macro(md2man source)
 | 
			
		|||
		file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man/man${SOURCE_SECTION})
 | 
			
		||||
		configure_file(${source} ${SOURCE_MANPAGE}.scdoc)
 | 
			
		||||
		add_custom_command(TARGET manpages
 | 
			
		||||
			COMMAND scdoc < ${SOURCE_MANPAGE}.scdoc > man/man${SOURCE_SECTION}/${SOURCE_MANPAGE})
 | 
			
		||||
			COMMAND mkdir -p man/man${SOURCE_SECTION} && scdoc < ${SOURCE_MANPAGE}.scdoc > man/man${SOURCE_SECTION}/${SOURCE_MANPAGE})
 | 
			
		||||
	endblock()
 | 
			
		||||
endmacro()
 | 
			
		||||
 | 
			
		||||
md2man(docs/lib${PROJECT_NAME}.7.md)
 | 
			
		||||
endif ()
 | 
			
		||||
md2man(./${PROJECT_NAME}-packager.1.md)
 | 
			
		||||
 | 
			
		||||
### Build documentation with Doxygen ###
 | 
			
		||||
 | 
			
		||||
if (not DISABLE_DOXYGEN)
 | 
			
		||||
find_package(Doxygen)
 | 
			
		||||
if (${DOXYGEN_FOUND})
 | 
			
		||||
# prefer scdocs for manpages.
 | 
			
		||||
set(DOXYGEN_GENERATE_MAN NO)
 | 
			
		||||
set(DOXYGEN_GENERATE_LATEX YES)
 | 
			
		||||
set(DOXYGEN_EXTRACT_ALL YES)
 | 
			
		||||
set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "docs/mainpage.md")
 | 
			
		||||
message(STATUS "Doxygen found, building docs.")
 | 
			
		||||
 | 
			
		||||
doxygen_add_docs(${PROJECT_NAME}_docs
 | 
			
		||||
	${HEADER_FILES}
 | 
			
		||||
	${SOURCE_FILES}
 | 
			
		||||
	USE_STAMP_FILE)
 | 
			
		||||
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_docs)
 | 
			
		||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
 | 
			
		||||
		  ${CMAKE_CURRENT_BINARY_DIR}/latex
 | 
			
		||||
	DESTINATION share/doc/${PROJECT_NAME}/doxygen)
 | 
			
		||||
add_dependencies(${PROJECT_NAME}_docs manpages)
 | 
			
		||||
endif () # DOXYGEN_FOUND?
 | 
			
		||||
endif () # DISABLE_DOXYGEN?
 | 
			
		||||
#if (not DISABLE_DOXYGEN)
 | 
			
		||||
#find_package(Doxygen)
 | 
			
		||||
#if (${DOXYGEN_FOUND})
 | 
			
		||||
## prefer scdocs for manpages.
 | 
			
		||||
#set(DOXYGEN_GENERATE_MAN NO)
 | 
			
		||||
#set(DOXYGEN_GENERATE_LATEX YES)
 | 
			
		||||
#set(DOXYGEN_EXTRACT_ALL YES)
 | 
			
		||||
#set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "docs/mainpage.md")
 | 
			
		||||
#message(STATUS "Doxygen found, building docs.")
 | 
			
		||||
#
 | 
			
		||||
#doxygen_add_docs(${PROJECT_NAME}_docs
 | 
			
		||||
#	${HEADER_FILES}
 | 
			
		||||
#	${SOURCE_FILES}
 | 
			
		||||
#	USE_STAMP_FILE)
 | 
			
		||||
#add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_docs)
 | 
			
		||||
#install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
 | 
			
		||||
#		  ${CMAKE_CURRENT_BINARY_DIR}/latex
 | 
			
		||||
#	DESTINATION share/doc/${PROJECT_NAME}/doxygen)
 | 
			
		||||
#add_dependencies(${PROJECT_NAME}_docs manpages)
 | 
			
		||||
#endif () # DOXYGEN_FOUND?
 | 
			
		||||
#endif () # DISABLE_DOXYGEN?
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,26 +2,21 @@
 | 
			
		|||
 | 
			
		||||
include(CMakePackageConfigHelpers)
 | 
			
		||||
 | 
			
		||||
### library packaging for CMake and pkgconfig to find built targets.
 | 
			
		||||
write_basic_package_version_file(
 | 
			
		||||
	${PROJECT_NAME}Config.cmake
 | 
			
		||||
	VERSION ${PACKAGE_VERSION}
 | 
			
		||||
	COMPATIBILITY SameMajorVersion
 | 
			
		||||
)
 | 
			
		||||
write_basic_package_version_file(
 | 
			
		||||
	${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
 | 
			
		||||
	VERSION ${PROJECT_VERSION}
 | 
			
		||||
	COMPATIBILITY SameMajorVersion)
 | 
			
		||||
configure_file(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
 | 
			
		||||
 | 
			
		||||
#### library packaging for CMake and pkgconfig to find built targets.
 | 
			
		||||
#write_basic_package_version_file(
 | 
			
		||||
#	${PROJECT_NAME}Config.cmake
 | 
			
		||||
#	VERSION ${PACKAGE_VERSION}
 | 
			
		||||
#	COMPATIBILITY SameMajorVersion
 | 
			
		||||
#)
 | 
			
		||||
#write_basic_package_version_file(
 | 
			
		||||
#	${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
 | 
			
		||||
#	VERSION ${PROJECT_VERSION}
 | 
			
		||||
#	COMPATIBILITY SameMajorVersion)
 | 
			
		||||
#configure_file(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
 | 
			
		||||
#
 | 
			
		||||
### set up installation targets.
 | 
			
		||||
 | 
			
		||||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib)
 | 
			
		||||
install(FILES ${HEADERS} DESTINATION include/${PROJECT_NAME})
 | 
			
		||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
 | 
			
		||||
	DESTINATION lib/pkgconfig)
 | 
			
		||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
 | 
			
		||||
	      ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
 | 
			
		||||
	DESTINATION share/${PROJECT_CMAKE_CONFIG_NAME}/cmake)
 | 
			
		||||
install(TARGETS ${PROJECT_NAME}-packager RUNTIME DESTINATION bin)
 | 
			
		||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man DESTINATION share)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
///
 | 
			
		||||
/// \file Debian.h
 | 
			
		||||
/// \author K. Isom <kyle@imap.cc>
 | 
			
		||||
/// \date 2023-10-24
 | 
			
		||||
/// \brief Functionality for interacting with Debian packages on Gitea.
 | 
			
		||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
 | 
			
		||||
///
 | 
			
		||||
/// Permission to use, copy, modify, and/or distribute this software for
 | 
			
		||||
/// any purpose with or without fee is hereby granted, provided that
 | 
			
		||||
/// the above copyright notice and this permission notice appear in all /// copies.
 | 
			
		||||
///
 | 
			
		||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | 
			
		||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | 
			
		||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | 
			
		||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | 
			
		||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | 
			
		||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
			
		||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
			
		||||
/// PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
#ifndef SC3DEV_DEBIAN_H
 | 
			
		||||
#define SC3DEV_DEBIAN_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool	debianPackager(std::vector<std::string> args);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif// SC3DEV_DEBIAN_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
///
 | 
			
		||||
/// \file Generic.h
 | 
			
		||||
/// \author K. Isom <kyle@imap.cc>
 | 
			
		||||
/// \date 2023-10-24
 | 
			
		||||
/// \brief Functionality for interacting with generic packages on
 | 
			
		||||
///        Gitea.
 | 
			
		||||
///
 | 
			
		||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
 | 
			
		||||
///
 | 
			
		||||
/// Permission to use, copy, modify, and/or distribute this software for
 | 
			
		||||
/// any purpose with or without fee is hereby granted, provided that
 | 
			
		||||
/// the above copyright notice and this permission notice appear in all /// copies.
 | 
			
		||||
///
 | 
			
		||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | 
			
		||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | 
			
		||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | 
			
		||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | 
			
		||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | 
			
		||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
			
		||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
			
		||||
/// PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
#ifndef SC3DEV_GENERIC_H
 | 
			
		||||
#define SC3DEV_GENERIC_H
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool	genericPackager(std::vector<std::string> args);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif// SC3DEV_GENERIC_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,51 @@
 | 
			
		|||
///
 | 
			
		||||
/// \file Utility.h
 | 
			
		||||
/// \author K. Isom <kyle@imap.cc>
 | 
			
		||||
/// \date 2023-10-24
 | 
			
		||||
/// \brief Common utility functions for packaging.
 | 
			
		||||
///
 | 
			
		||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
 | 
			
		||||
///
 | 
			
		||||
/// Permission to use, copy, modify, and/or distribute this software for
 | 
			
		||||
/// any purpose with or without fee is hereby granted, provided that
 | 
			
		||||
/// the above copyright notice and this permission notice appear in all /// copies.
 | 
			
		||||
///
 | 
			
		||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | 
			
		||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | 
			
		||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | 
			
		||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | 
			
		||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | 
			
		||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
			
		||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
			
		||||
/// PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
#ifndef SC3DEV_UTILITY_H
 | 
			
		||||
#define SC3DEV_UTILITY_H
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const auto defaultOwner        = std::string("sc");
 | 
			
		||||
static const auto defaultDistribution = std::string("ubuntu");
 | 
			
		||||
static const auto defaultComponent    = std::string("main");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
enum class Result {
 | 
			
		||||
	Created = 0,
 | 
			
		||||
	BadPackage = 1,
 | 
			
		||||
	DuplicatePackage = 2,
 | 
			
		||||
	Deleted = 3,
 | 
			
		||||
	NotFound = 4,
 | 
			
		||||
	CurlFailed = 5,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::string 	ResultToString(Result result);
 | 
			
		||||
bool		ResultSuccess(Result result);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Result		PutFile(std::string url, std::string path);
 | 
			
		||||
Result		DeleteFile(std::string url);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif// SC3DEV_UTILITY_H
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,93 @@
 | 
			
		|||
sc3dev-packager(1) "@PROJECT_VERSION@"
 | 
			
		||||
 | 
			
		||||
# NAME
 | 
			
		||||
 | 
			
		||||
sc3dev-packager - interact with Gitea package repos
 | 
			
		||||
 | 
			
		||||
# SYNOPSIS
 | 
			
		||||
 | 
			
		||||
sc3dev-packager [flags] repo command package-names...
 | 
			
		||||
 | 
			
		||||
# DESCRIPTION
 | 
			
		||||
 | 
			
		||||
sc3dev-packager is a tool for uploading and deleting packages from
 | 
			
		||||
Gitea servers.
 | 
			
		||||
 | 
			
		||||
Flags:
 | 
			
		||||
 | 
			
		||||
*--component component*
 | 
			
		||||
	Select the package component (Debian-only). Defaults to 'main'.
 | 
			
		||||
 | 
			
		||||
*--config path*
 | 
			
		||||
	The path to a simple config file that should be used.
 | 
			
		||||
 | 
			
		||||
*--distribution distribution*
 | 
			
		||||
	Select the package distribution (Debian-only). Defaults to 'ubuntu'.
 | 
			
		||||
 | 
			
		||||
*--owner owner*
 | 
			
		||||
	Select the owner of the package repository. Defaults to 'sc'.
 | 
			
		||||
 | 
			
		||||
*--verbose*
 | 
			
		||||
	Show verbose cURL output.
 | 
			
		||||
 | 
			
		||||
Repositories:
 | 
			
		||||
 | 
			
		||||
The supported repositories are:
 | 
			
		||||
 | 
			
		||||
- debian
 | 
			
		||||
- generic
 | 
			
		||||
 | 
			
		||||
Commands:
 | 
			
		||||
 | 
			
		||||
- del removes the package from the repository. Deleted packages don't
 | 
			
		||||
  have to exist on disk.
 | 
			
		||||
- put uploads the package to the repository.
 | 
			
		||||
 | 
			
		||||
# EXAMPLES
 | 
			
		||||
 | 
			
		||||
*sc3dev-packager --owner joe debian put /path/to/package_1.0.0_amd64.deb*
 | 
			
		||||
	Upload package_1.0.0_amd64.deb to the Debian package repository
 | 
			
		||||
	owned by 'joe'.
 | 
			
		||||
 | 
			
		||||
*sc3dev-packager --owner bob generic del package-1.0.0-Linux-x86_64.tar.gz.sh*
 | 
			
		||||
	Remove package-1.0.0-Linux-x86_64.tar.gz from the generic package
 | 
			
		||||
	repository owned by 'bob'.
 | 
			
		||||
 | 
			
		||||
# Configuration
 | 
			
		||||
 | 
			
		||||
This uses an SCSL simple configuration to gather data. Valid variables
 | 
			
		||||
that can be configured:
 | 
			
		||||
 | 
			
		||||
- component
 | 
			
		||||
- distribution
 | 
			
		||||
- http_user: the user name to authenticate as
 | 
			
		||||
- http_pass: the password to authenticate with
 | 
			
		||||
- owner
 | 
			
		||||
- server: no protocol information, only the hostname (and optionally port).
 | 
			
		||||
- verbose: if not set from the commandline, it should be the string "true".
 | 
			
		||||
 | 
			
		||||
Example configuration:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
owner = someorg
 | 
			
		||||
http_user = joe
 | 
			
		||||
http_pass = correct horse battery staple
 | 
			
		||||
server = git.example.com
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Alternatively, any of these variables may be set on the command line:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
owner=joe sc3dev-packager debian put newpkg_1.0.1_arm64.deb
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
# FILES
 | 
			
		||||
 | 
			
		||||
*/etc/sc3dev/packager.conf*
 | 
			
		||||
	The default configuration file path if run as root.
 | 
			
		||||
*$HOME/.config/sc3dev-packager.conf*
 | 
			
		||||
	The default configuration path if run as a user.
 | 
			
		||||
 | 
			
		||||
# SEE ALSO
 | 
			
		||||
 | 
			
		||||
The project's homepage is on [Gitea](https://git.wntrmute.dev/sc/sc3dev).
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,122 @@
 | 
			
		|||
///
 | 
			
		||||
/// \file Debian.cc
 | 
			
		||||
/// \author K. Isom <kyle@imap.cc>
 | 
			
		||||
/// \date 2023-10-24
 | 
			
		||||
/// \brief Functionality for interacting with Debian packages on Gitea.
 | 
			
		||||
///
 | 
			
		||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
 | 
			
		||||
///
 | 
			
		||||
/// Permission to use, copy, modify, and/or distribute this software for
 | 
			
		||||
/// any purpose with or without fee is hereby granted, provided that
 | 
			
		||||
/// the above copyright notice and this permission notice appear in all /// copies.
 | 
			
		||||
///
 | 
			
		||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | 
			
		||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | 
			
		||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | 
			
		||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | 
			
		||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | 
			
		||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
			
		||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
			
		||||
/// PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <scsl/Commander.h>
 | 
			
		||||
#include <scsl/SimpleConfig.h>
 | 
			
		||||
#include <scsl/StringUtil.h>
 | 
			
		||||
 | 
			
		||||
#include "Debian.h"
 | 
			
		||||
#include "Utility.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
std::string
 | 
			
		||||
debianEndpoint(std::string endpoint)
 | 
			
		||||
{
 | 
			
		||||
	if (!endpoint.empty() && endpoint.at(0) != '/') {
 | 
			
		||||
		endpoint.insert(endpoint.cbegin(), '/');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::cerr << "owner: " << scsl::SimpleConfig::GetGlobal("owner", defaultOwner) << "\n";
 | 
			
		||||
	auto urlBase = "https://" + scsl::SimpleConfig::GetGlobal("server");
 | 
			
		||||
	return urlBase + "/api/packages/" +
 | 
			
		||||
	       scsl::SimpleConfig::GetGlobal("owner", defaultOwner) +
 | 
			
		||||
	       "/debian/pool/" +
 | 
			
		||||
	       scsl::SimpleConfig::GetGlobal("distribution", defaultDistribution) +
 | 
			
		||||
	       "/" +
 | 
			
		||||
	       scsl::SimpleConfig::GetGlobal("component", defaultComponent) +
 | 
			
		||||
	       endpoint;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
std::string
 | 
			
		||||
endpointForPackage(std::string package)
 | 
			
		||||
{
 | 
			
		||||
	const std::filesystem::path pkgAsPath(package);
 | 
			
		||||
 | 
			
		||||
	auto stem  = pkgAsPath.stem();
 | 
			
		||||
	auto parts = scsl::scstring::SplitN(stem, "_", 3);
 | 
			
		||||
	if (parts.size() != 3) {
 | 
			
		||||
		return "";
 | 
			
		||||
	}
 | 
			
		||||
	return parts[0] + "/" + parts[1] + "/" + parts[2];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
putDebian(std::vector<std::string> args)
 | 
			
		||||
{
 | 
			
		||||
	auto ok = true;
 | 
			
		||||
	for (auto &arg: args) {
 | 
			
		||||
		auto url    = debianEndpoint("upload");
 | 
			
		||||
		auto result = PutFile(url, arg);
 | 
			
		||||
		std::cout << "\t[*] PUT " << std::filesystem::path(arg).filename() << ": ";
 | 
			
		||||
		std::cout << ResultToString(result) << "\n";
 | 
			
		||||
		ok &= ResultSuccess(result);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
deleteDebian(std::vector<std::string> args)
 | 
			
		||||
{
 | 
			
		||||
	auto ok = true;
 | 
			
		||||
 | 
			
		||||
	for (auto &arg: args) {
 | 
			
		||||
		auto endpoint = endpointForPackage(arg);
 | 
			
		||||
		if (endpoint.empty()) {
 | 
			
		||||
			std::cerr << arg << ": invalid filename\n";
 | 
			
		||||
			ok &= false;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		auto url      = debianEndpoint(endpoint);
 | 
			
		||||
		std::cerr << "URL: " << url << "\n";
 | 
			
		||||
		auto result = DeleteFile(url);
 | 
			
		||||
		std::cout << "\t[*] DELETE " << std::filesystem::path(arg).filename() << ": ";
 | 
			
		||||
		std::cout << ResultToString(result) << "\n";
 | 
			
		||||
		ok &= ResultSuccess(result);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ok;
 | 
			
		||||
}
 | 
			
		||||
}// anonymous namespace
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
debianPackager(std::vector<std::string> args)
 | 
			
		||||
{
 | 
			
		||||
	scsl::Commander commander;
 | 
			
		||||
	commander.Register(scsl::Subcommand("del", 1, deleteDebian));
 | 
			
		||||
	commander.Register(scsl::Subcommand("put", 1, putDebian));
 | 
			
		||||
 | 
			
		||||
	auto command = args[0];
 | 
			
		||||
	args.erase(args.cbegin());
 | 
			
		||||
	return commander.Run(command, args) == scsl::Subcommand::Status::OK;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,117 @@
 | 
			
		|||
///
 | 
			
		||||
/// \file Generic.cc
 | 
			
		||||
/// \author K. Isom <kyle@imap.cc>
 | 
			
		||||
/// \date 2023-10-24
 | 
			
		||||
/// \brief Functionality for interacting with generic packages on
 | 
			
		||||
///        Gitea.
 | 
			
		||||
///
 | 
			
		||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
 | 
			
		||||
///
 | 
			
		||||
/// Permission to use, copy, modify, and/or distribute this software for
 | 
			
		||||
/// any purpose with or without fee is hereby granted, provided that
 | 
			
		||||
/// the above copyright notice and this permission notice appear in all /// copies.
 | 
			
		||||
///
 | 
			
		||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | 
			
		||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | 
			
		||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | 
			
		||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | 
			
		||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | 
			
		||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
			
		||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
			
		||||
/// PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <scsl/Commander.h>
 | 
			
		||||
#include <scsl/SimpleConfig.h>
 | 
			
		||||
#include <scsl/StringUtil.h>
 | 
			
		||||
 | 
			
		||||
#include "Utility.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
std::string
 | 
			
		||||
genericEndpoint(std::string endpoint)
 | 
			
		||||
{
 | 
			
		||||
	if (!endpoint.empty() && endpoint.at(0) != '/') {
 | 
			
		||||
		endpoint.insert(endpoint.cbegin(), '/');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::cerr << "owner: " << scsl::SimpleConfig::GetGlobal("owner", defaultOwner) << "\n";
 | 
			
		||||
	auto urlBase = "https://" + scsl::SimpleConfig::GetGlobal("server");
 | 
			
		||||
	return urlBase + "/api/packages/" +
 | 
			
		||||
	       scsl::SimpleConfig::GetGlobal("owner", defaultOwner) +
 | 
			
		||||
	       "/generic" + endpoint;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
std::string
 | 
			
		||||
endpointForPackage(std::string package)
 | 
			
		||||
{
 | 
			
		||||
	const std::filesystem::path pkgAsPath(package);
 | 
			
		||||
 | 
			
		||||
	auto stem  = pkgAsPath.stem();
 | 
			
		||||
	auto parts = scsl::scstring::SplitN(stem, "-", 3);
 | 
			
		||||
	if (parts.size() < 2) {
 | 
			
		||||
		return "";
 | 
			
		||||
	}
 | 
			
		||||
	return parts[0] + "/" + parts[1] + "/" + pkgAsPath.filename().string();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
putGeneric(std::vector<std::string> args)
 | 
			
		||||
{
 | 
			
		||||
	auto ok = true;
 | 
			
		||||
	for (auto &arg: args) {
 | 
			
		||||
		auto url    = genericEndpoint(endpointForPackage(arg));
 | 
			
		||||
		auto result = PutFile(url, arg);
 | 
			
		||||
		std::cout << "\t[*] PUT " << std::filesystem::path(arg).filename() << ": ";
 | 
			
		||||
		std::cout << ResultToString(result) << "\n";
 | 
			
		||||
		ok &= ResultSuccess(result);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
deleteGeneric(std::vector<std::string> args)
 | 
			
		||||
{
 | 
			
		||||
	auto ok = true;
 | 
			
		||||
 | 
			
		||||
	for (auto &arg: args) {
 | 
			
		||||
		auto endpoint = endpointForPackage(arg);
 | 
			
		||||
		if (endpoint.empty()) {
 | 
			
		||||
			std::cerr << arg << ": invalid filename\n";
 | 
			
		||||
			ok &= false;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		auto url      = genericEndpoint(endpoint);
 | 
			
		||||
		std::cerr << "URL: " << url << "\n";
 | 
			
		||||
		auto result = DeleteFile(url);
 | 
			
		||||
		std::cout << "\t[*] DELETE " << std::filesystem::path(arg).filename() << ": ";
 | 
			
		||||
		std::cout << ResultToString(result) << "\n";
 | 
			
		||||
		ok &= ResultSuccess(result);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ok;
 | 
			
		||||
}
 | 
			
		||||
}// anonymous namespace
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
genericPackager(std::vector<std::string> args)
 | 
			
		||||
{
 | 
			
		||||
	scsl::Commander commander;
 | 
			
		||||
	commander.Register(scsl::Subcommand("del", 1, deleteGeneric));
 | 
			
		||||
	commander.Register(scsl::Subcommand("put", 1, putGeneric));
 | 
			
		||||
 | 
			
		||||
	auto command = args[0];
 | 
			
		||||
	args.erase(args.cbegin());
 | 
			
		||||
	return commander.Run(command, args) == scsl::Subcommand::Status::OK;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,180 @@
 | 
			
		|||
///
 | 
			
		||||
/// \file Utility.cc
 | 
			
		||||
/// \author K. Isom <kyle@imap.cc>
 | 
			
		||||
/// \date 2023-10-24
 | 
			
		||||
/// \brief Common utility functions for packaging.
 | 
			
		||||
///
 | 
			
		||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
 | 
			
		||||
///
 | 
			
		||||
/// Permission to use, copy, modify, and/or distribute this software for
 | 
			
		||||
/// any purpose with or without fee is hereby granted, provided that
 | 
			
		||||
/// the above copyright notice and this permission notice appear in all /// copies.
 | 
			
		||||
///
 | 
			
		||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | 
			
		||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | 
			
		||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | 
			
		||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | 
			
		||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | 
			
		||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
			
		||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
			
		||||
/// PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
#include <curlpp/Easy.hpp>
 | 
			
		||||
#include <curlpp/Infos.hpp>
 | 
			
		||||
#include <curlpp/Options.hpp>
 | 
			
		||||
#include <curlpp/cURLpp.hpp>
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <scsl/SimpleConfig.h>
 | 
			
		||||
 | 
			
		||||
#include "Utility.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
std::string
 | 
			
		||||
getUserPass()
 | 
			
		||||
{
 | 
			
		||||
	return scsl::SimpleConfig::GetGlobal("http_user") + ":" +
 | 
			
		||||
	       scsl::SimpleConfig::GetGlobal("http_password");
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Result
 | 
			
		||||
PutFile(std::string url, std::string path)
 | 
			
		||||
{
 | 
			
		||||
	const curlpp::Cleanup clearerr;
 | 
			
		||||
	static std::string userPass;
 | 
			
		||||
	auto verbose = false;
 | 
			
		||||
	curlpp::Easy request;
 | 
			
		||||
 | 
			
		||||
	if (scsl::SimpleConfig::GetGlobal("verbose") == "true") {
 | 
			
		||||
		verbose = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (userPass.empty()) {
 | 
			
		||||
		userPass = getUserPass();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	try {
 | 
			
		||||
		std::list<std::string> header;
 | 
			
		||||
		header.emplace_back("Content-Type: application/octet-stream");
 | 
			
		||||
 | 
			
		||||
		if (!std::filesystem::exists(path)) {
 | 
			
		||||
			std::cerr << "[!] " << path << " does not exist!\n";
 | 
			
		||||
			return Result::CurlFailed;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
		auto fileSize = static_cast<int64_t>(std::filesystem::file_size(path));
 | 
			
		||||
 | 
			
		||||
		std::ifstream uploadFile(path);
 | 
			
		||||
		if (!uploadFile.good()) {
 | 
			
		||||
			std::cerr << "[!] " << path << " does not exist!\n";
 | 
			
		||||
			return Result::CurlFailed;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		request.setOpt(new curlpp::options::Url(url));
 | 
			
		||||
		if (verbose) {
 | 
			
		||||
			request.setOpt(new curlpp::options::Verbose(true));
 | 
			
		||||
		}		request.setOpt(new curlpp::options::UserPwd(userPass));
 | 
			
		||||
		request.setOpt(new curlpp::Options::ReadStream(&uploadFile));
 | 
			
		||||
		request.setOpt(new curlpp::Options::InfileSize(fileSize));
 | 
			
		||||
		request.setOpt(new curlpp::Options::Upload(true));
 | 
			
		||||
		request.perform();
 | 
			
		||||
	} catch (curlpp::LogicError &e) {
 | 
			
		||||
		std::cerr << e.what() << "\n";
 | 
			
		||||
		return Result::CurlFailed;
 | 
			
		||||
	} catch (curlpp::RuntimeError &e) {
 | 
			
		||||
		std::cerr << e.what() << "\n";
 | 
			
		||||
		return Result::CurlFailed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto httpStatus = curlpp::infos::ResponseCode::get(request);
 | 
			
		||||
	switch (httpStatus) {
 | 
			
		||||
	case 201:
 | 
			
		||||
		return Result::Created;
 | 
			
		||||
	case 400:
 | 
			
		||||
		return Result::BadPackage;
 | 
			
		||||
	case 409:
 | 
			
		||||
		return Result::DuplicatePackage;
 | 
			
		||||
	default:
 | 
			
		||||
		return Result::CurlFailed;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Result
 | 
			
		||||
DeleteFile(std::string url)
 | 
			
		||||
{
 | 
			
		||||
	const curlpp::Cleanup clearerr;
 | 
			
		||||
	static std::string userPass;
 | 
			
		||||
	bool verbose = false;
 | 
			
		||||
	curlpp::Easy request;
 | 
			
		||||
 | 
			
		||||
	if (scsl::SimpleConfig::GetGlobal("verbose") == "true") {
 | 
			
		||||
		verbose = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if (userPass.empty()) {
 | 
			
		||||
		userPass = getUserPass();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	try {
 | 
			
		||||
 | 
			
		||||
		request.setOpt(new curlpp::options::Url(url));
 | 
			
		||||
		if (verbose) {
 | 
			
		||||
			request.setOpt(new curlpp::options::Verbose(true));
 | 
			
		||||
		}
 | 
			
		||||
		request.setOpt(new curlpp::options::UserPwd(userPass));
 | 
			
		||||
		request.setOpt(new curlpp::Options::CustomRequest ("DELETE"));
 | 
			
		||||
		request.perform();
 | 
			
		||||
	} catch (curlpp::LogicError &e) {
 | 
			
		||||
		std::cerr << e.what() << "\n";
 | 
			
		||||
		return Result::CurlFailed;
 | 
			
		||||
	} catch (curlpp::RuntimeError &e) {
 | 
			
		||||
		std::cerr << e.what() << "\n";
 | 
			
		||||
		return Result::CurlFailed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto httpStatus = curlpp::infos::ResponseCode::get(request);
 | 
			
		||||
	switch (httpStatus) {
 | 
			
		||||
	case 204:
 | 
			
		||||
		return Result::Deleted;
 | 
			
		||||
	case 404:
 | 
			
		||||
		return Result::NotFound;
 | 
			
		||||
	default:
 | 
			
		||||
		return Result::CurlFailed;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
std::string
 | 
			
		||||
ResultToString(Result result)
 | 
			
		||||
{
 | 
			
		||||
	switch (result) {
 | 
			
		||||
	case Result::Created:
 | 
			
		||||
		return "OK: created";
 | 
			
		||||
	case Result::BadPackage:
 | 
			
		||||
		return "FAILED: bad package";
 | 
			
		||||
	case Result::DuplicatePackage:
 | 
			
		||||
		return "FAILED: duplicate package?";
 | 
			
		||||
	case Result::Deleted:
 | 
			
		||||
		return "OK: deleted";
 | 
			
		||||
	case Result::NotFound:
 | 
			
		||||
		return "FAILED: not found";
 | 
			
		||||
	case Result::CurlFailed:
 | 
			
		||||
		return "FAILED: curl failed";
 | 
			
		||||
	default:
 | 
			
		||||
		return "FAILED: unhandled error";
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
ResultSuccess(Result result)
 | 
			
		||||
{
 | 
			
		||||
	return (result == Result::Created || result == Result::Deleted);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										160
									
								
								src/packager.cc
								
								
								
								
							
							
						
						
									
										160
									
								
								src/packager.cc
								
								
								
								
							| 
						 | 
				
			
			@ -4,34 +4,46 @@
 | 
			
		|||
/// \date 2023-10-18
 | 
			
		||||
/// \brief Packaging tools for shimmering-clarity.
 | 
			
		||||
///
 | 
			
		||||
/// Copyright 2023 K. Isom <kyle@imap.cc>
 | 
			
		||||
///
 | 
			
		||||
/// Permission to use, copy, modify, and/or distribute this software for
 | 
			
		||||
/// any purpose with or without fee is hereby granted, provided that
 | 
			
		||||
/// the above copyright notice and this permission notice appear in all /// copies.
 | 
			
		||||
///
 | 
			
		||||
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 | 
			
		||||
/// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 | 
			
		||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 | 
			
		||||
/// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 | 
			
		||||
/// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 | 
			
		||||
/// OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
			
		||||
/// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
			
		||||
/// PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include <curlpp/Easy.hpp>
 | 
			
		||||
#include <curlpp/Exception.hpp>
 | 
			
		||||
#include <curlpp/Options.hpp>
 | 
			
		||||
#include <curlpp/cURLpp.hpp>
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <scsl/Commander.h>
 | 
			
		||||
#include <scsl/Flags.h>
 | 
			
		||||
#include <scsl/SimpleConfig.h>
 | 
			
		||||
 | 
			
		||||
#include "Debian.h"
 | 
			
		||||
#include "Generic.h"
 | 
			
		||||
#include "Utility.h"
 | 
			
		||||
 | 
			
		||||
const auto defaultOwner        = std::string("sc");
 | 
			
		||||
const auto defaultDistribution = std::string("ubuntu");
 | 
			
		||||
const auto defaultComponent    = std::string("main");
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
usage(std::ostream &outs, int exc)
 | 
			
		||||
{
 | 
			
		||||
	outs << "sc3dev-packager: manage packages on gitea\n";
 | 
			
		||||
	outs << "usage:\n";
 | 
			
		||||
	outs << "\tsc3dev-packager [--component component] [--owner owner] \n";
 | 
			
		||||
	outs << "\t\t[--distribution distribution] debian command packages ...\n";
 | 
			
		||||
	outs << "\tsc3dev-packager [--owner owner] generic command packages ...\n";
 | 
			
		||||
	outs << "\tsc3dev-packager [--component component] [--distribution distribution]\n";
 | 
			
		||||
	outs << "\t\t debian command packages ...\n";
 | 
			
		||||
	outs << "\tsc3dev-packager generic command packages ...\n";
 | 
			
		||||
	outs << "\nGlobal flags:\n";
 | 
			
		||||
	outs << "\t[--owner owner]\n";
 | 
			
		||||
	outs << "\t[--verbose]\n";
 | 
			
		||||
	outs << "\nCommands:\n";
 | 
			
		||||
	outs << "\t- delete: remove a package\n";
 | 
			
		||||
	outs << "\t- put: upload a package\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -43,8 +55,8 @@ usage(std::ostream &outs, int exc)
 | 
			
		|||
std::string
 | 
			
		||||
getDefaultConfigFile()
 | 
			
		||||
{
 | 
			
		||||
	auto userEnv = getenv("USER");
 | 
			
		||||
	auto user    = std::string(userEnv);
 | 
			
		||||
	auto *userEnv = getenv("USER");
 | 
			
		||||
	auto  user     = std::string(userEnv);
 | 
			
		||||
 | 
			
		||||
	if (user == "root") {
 | 
			
		||||
		return std::filesystem::path("/etc/sc3dev/packager.conf");
 | 
			
		||||
| 
						 | 
				
			
			@ -58,124 +70,29 @@ getDefaultConfigFile()
 | 
			
		|||
	auto userHome = std::filesystem::path(userEnv);
 | 
			
		||||
 | 
			
		||||
	userHome /= std::filesystem::path(".config");
 | 
			
		||||
	userHome /= std::filesystem::path("sc3dev-packager.conf");
 | 
			
		||||
	userHome /= std::filesystem::path("sc3dev");
 | 
			
		||||
	userHome /= std::filesystem::path("packager.conf");
 | 
			
		||||
	return userHome;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static std::string
 | 
			
		||||
debianEndpoint(std::string endpoint)
 | 
			
		||||
{
 | 
			
		||||
	if (!endpoint.empty() && endpoint.at(0) != '/') {
 | 
			
		||||
		endpoint.insert(endpoint.cbegin(), '/');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto urlBase = scsl::SimpleConfig::GetGlobal("server");
 | 
			
		||||
	return urlBase + "/api/packages/" +
 | 
			
		||||
	       scsl::SimpleConfig::GetGlobal("owner", defaultOwner) +
 | 
			
		||||
	       "/debian/pool/" +
 | 
			
		||||
	       scsl::SimpleConfig::GetGlobal("distribution", defaultDistribution) +
 | 
			
		||||
	       "/" +
 | 
			
		||||
	       scsl::SimpleConfig::GetGlobal("component", defaultComponent) +
 | 
			
		||||
	       endpoint;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static std::string
 | 
			
		||||
getUserPass()
 | 
			
		||||
{
 | 
			
		||||
	return scsl::SimpleConfig::GetGlobal("http_user") + ":" +
 | 
			
		||||
	       scsl::SimpleConfig::GetGlobal("http_password");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
putDebian(std::vector<std::string> args)
 | 
			
		||||
{
 | 
			
		||||
	auto ok = true;
 | 
			
		||||
	std::cout << "[+] put Debian package\n";
 | 
			
		||||
	for (auto &arg: args) {
 | 
			
		||||
		std::cout << "\t[*] " << arg << "\n";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto url      = debianEndpoint("upload");
 | 
			
		||||
	auto userPass = getUserPass();
 | 
			
		||||
	for (auto &arg: args) {
 | 
			
		||||
		try {
 | 
			
		||||
			std::list<std::string> header;
 | 
			
		||||
			header.emplace_back("Content-Type: application/octet-stream");
 | 
			
		||||
 | 
			
		||||
			curlpp::Cleanup cleaner;
 | 
			
		||||
			curlpp::Easy request;
 | 
			
		||||
 | 
			
		||||
			if (!std::filesystem::exists(arg)) {
 | 
			
		||||
				std::cerr << "[!] " << arg << " does not exist!\n";
 | 
			
		||||
				ok &= false;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			auto fileSize = static_cast<long>(std::filesystem::file_size(arg));
 | 
			
		||||
 | 
			
		||||
			std::ifstream debFile(arg);
 | 
			
		||||
			if (!debFile.good()) {
 | 
			
		||||
				std::cerr << "[!] " << arg << " does not exist!\n";
 | 
			
		||||
				ok &= false;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			request.setOpt(new curlpp::options::Url(url));
 | 
			
		||||
			request.setOpt(new curlpp::options::Verbose(true));
 | 
			
		||||
			request.setOpt(new curlpp::options::UserPwd(userPass));
 | 
			
		||||
			request.setOpt(new curlpp::Options::ReadStream(&debFile));
 | 
			
		||||
			request.setOpt(new curlpp::Options::InfileSize(fileSize));
 | 
			
		||||
			request.setOpt(new curlpp::Options::Upload(true));
 | 
			
		||||
			request.perform();
 | 
			
		||||
		} catch (curlpp::LogicError &e) {
 | 
			
		||||
			std::cout << e.what() << "\n";
 | 
			
		||||
			ok &= false;
 | 
			
		||||
		} catch (curlpp::RuntimeError &e) {
 | 
			
		||||
			std::cerr << e.what() << "\n";
 | 
			
		||||
			ok &= false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		std::cout << "[+] " << std::filesystem::path(arg).filename() << ": OK\n";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
debianPackager(std::vector<std::string> args)
 | 
			
		||||
{
 | 
			
		||||
	scsl::Commander commander;
 | 
			
		||||
	commander.Register(scsl::Subcommand("put", 1, putDebian));
 | 
			
		||||
 | 
			
		||||
	std::cout << "[+] Debian packager invoked\n";
 | 
			
		||||
	for (auto &arg: args) {
 | 
			
		||||
		std::cout << "\t[*] " << arg << "\n";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto command = args[0];
 | 
			
		||||
	args.erase(args.cbegin());
 | 
			
		||||
	return commander.Run(command, args) == scsl::Subcommand::Status::OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	int retc;
 | 
			
		||||
	scsl::Flags *flags;
 | 
			
		||||
	int retc = -1;
 | 
			
		||||
	scsl::Flags *flags = nullptr;
 | 
			
		||||
	std::string configFile = getDefaultConfigFile();
 | 
			
		||||
	std::string owner;
 | 
			
		||||
	std::string distribution;
 | 
			
		||||
	std::string component;
 | 
			
		||||
	std::string version;
 | 
			
		||||
	bool verbose;
 | 
			
		||||
 | 
			
		||||
	flags = new scsl::Flags("sc3dev-packager", "package tooling for shimmering clarity");
 | 
			
		||||
	flags->Register("--config", configFile, "path to a configuration file");
 | 
			
		||||
	flags->Register("--component", "main", "Debian package component");
 | 
			
		||||
	flags->Register("--distribution", "ubuntu", "Debian package distribution");
 | 
			
		||||
	flags->Register("--owner", "sc", "package repository owner");
 | 
			
		||||
	flags->Register("--version", scsl::FlagType::String, "version to operate on (only matters for delete)");
 | 
			
		||||
	flags->Register("--component", defaultComponent, "Debian package component");
 | 
			
		||||
	flags->Register("--distribution", defaultDistribution, "Debian package distribution");
 | 
			
		||||
	flags->Register("--owner", defaultOwner, "package repository owner");
 | 
			
		||||
	flags->Register("--verbose", false, "use verbose CURL endpoints");
 | 
			
		||||
 | 
			
		||||
	auto status = flags->Parse(argc, argv);
 | 
			
		||||
	if (status != scsl::Flags::ParseStatus::OK) {
 | 
			
		||||
| 
						 | 
				
			
			@ -186,7 +103,8 @@ main(int argc, char *argv[])
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	scsl::Commander commander;
 | 
			
		||||
	commander.Register(scsl::Subcommand("debian", 1, debianPackager));
 | 
			
		||||
	commander.Register(scsl::Subcommand("debian", 2, debianPackager));
 | 
			
		||||
	commander.Register(scsl::Subcommand("generic", 2, genericPackager));
 | 
			
		||||
 | 
			
		||||
	flags->GetString("--config", configFile);
 | 
			
		||||
	if (std::filesystem::exists(std::filesystem::path(configFile))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -208,8 +126,8 @@ main(int argc, char *argv[])
 | 
			
		|||
		scsl::SimpleConfig::PutGlobal("component", component);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags->GetString("--version", version)) {
 | 
			
		||||
		scsl::SimpleConfig::PutGlobal("version", version);
 | 
			
		||||
	if (flags->GetBool("--verbose", verbose)) {
 | 
			
		||||
		scsl::SimpleConfig::PutGlobal("verbose", "true");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (flags->NumArgs() < 1) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue