!> Upload a package to the registry using the `publish` command. !> !> To upload a package you need to provide a token that will be linked to your username and created for a namespace. !> The token can be obtained from the registry website. It can be used as `fpm publish --token <token>`. module fpm_cmd_publish use fpm_command_line, only: fpm_publish_settings use fpm_manifest, only: package_config_t, get_package_data use fpm_model, only: fpm_model_t use fpm_error, only: error_t, fpm_stop use fpm_versioning, only: version_t use fpm_filesystem, only: exists, join_path, get_temp_filename, delete_file use fpm_git, only: git_archive use fpm_downloader, only: downloader_t use fpm_strings, only: string_t use fpm_settings, only: official_registry_base_url use fpm, only: build_model implicit none private public :: cmd_publish contains !> The `publish` command first builds the root package to obtain all the relevant information such as the !> package version. It then creates a tarball of the package and uploads it to the registry. subroutine cmd_publish(settings) type(fpm_publish_settings), intent(inout) :: settings type(package_config_t) :: package type(fpm_model_t) :: model type(error_t), allocatable :: error type(version_t), allocatable :: version type(string_t), allocatable :: upload_data(:) character(len=:), allocatable :: tmp_file type(downloader_t) :: downloader integer :: i ! Get package data to determine package version. call get_package_data(package, 'fpm.toml', error, apply_defaults=.true.) if (allocated(error)) call fpm_stop(1, '*cmd_build* Package error: '//error%message) version = package%version if (settings%show_package_version) then print *, version%s(); return end if !> Checks before uploading the package. if (.not. allocated(package%license)) call fpm_stop(1, 'No license specified in fpm.toml.') if (.not. package%build%module_naming) call fpm_stop(1, 'The package does not meet the module naming requirements. '// & & 'Please set "module-naming = true" in fpm.toml [build] or specify a custom module prefix.') if (.not. allocated(version)) call fpm_stop(1, 'No version specified in fpm.toml.') if (version%s() == '0') call fpm_stop(1, 'Invalid version: "'//version%s()//'".') if (.not. exists('fpm.toml')) call fpm_stop(1, "Cannot find 'fpm.toml' file. Are you in the project root?") ! Build model to obtain dependency tree. call build_model(model, settings%fpm_build_settings, package, error) if (allocated(error)) call fpm_stop(1, '*cmd_build* Model error: '//error%message) ! Check if package contains git dependencies. Only publish packages without git dependencies. do i = 1, model%deps%ndep if (allocated(model%deps%dep(i)%git)) then call fpm_stop(1, 'Do not publish packages containing git dependencies. '// & & "Please upload '"//model%deps%dep(i)%name//"' to the registry first.") end if end do tmp_file = get_temp_filename() call git_archive('.', tmp_file, 'HEAD', additional_files=['fpm_model.json'], verbose=settings%verbose, error=error) if (allocated(error)) call fpm_stop(1, '*cmd_publish* Archive error: '//error%message) call model%dump('fpm_model.json', error, json=.true.) if (allocated(error)) call fpm_stop(1, '*cmd_publish* Model dump error: '//error%message) upload_data = [ & & string_t('package_name="'//package%name//'"'), & & string_t('package_license="'//package%license//'"'), & & string_t('package_version="'//version%s()//'"'), & & string_t('tarball=@"'//tmp_file//'"') & & ] if (allocated(settings%token)) upload_data = [upload_data, string_t('upload_token="'//settings%token//'"')] if (settings%show_upload_data) then call print_upload_data(upload_data); return end if ! Make sure a token is provided for publishing. if (allocated(settings%token)) then if (settings%token == '') then call delete_file(tmp_file); call fpm_stop(1, 'No token provided.') end if else call delete_file(tmp_file); call fpm_stop(1, 'No token provided.') end if if (settings%verbose) then call print_upload_data(upload_data) print *, '' end if ! Perform network request and validate package, token etc. on the backend once ! https://github.com/fortran-lang/registry/issues/41 is resolved. if (settings%is_dry_run) then print *, 'Dry run successful. Generated tarball: ', tmp_file; return end if call downloader%upload_form(official_registry_base_url//'/packages', upload_data, settings%verbose, error) call delete_file(tmp_file) if (allocated(error)) call fpm_stop(1, '*cmd_publish* Upload error: '//error%message) end subroutine print_upload_data(upload_data) type(string_t), intent(in) :: upload_data(:) integer :: i print *, 'Upload data:' do i = 1, size(upload_data) print *, upload_data(i)%s end do end end