aboutsummaryrefslogtreecommitdiff
path: root/scripts/cmake/vcpkg_from_git.cmake
blob: d2055f82e073111dcb3aacfb6337df009c90bcee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#[===[.md:
# vcpkg_from_git

Download and extract a project from git

## Usage:
```cmake
vcpkg_from_git(
    OUT_SOURCE_PATH <SOURCE_PATH>
    URL <https://android.googlesource.com/platform/external/fdlibm>
    REF <59f7335e4d...>
    [TAG <v1.0.2>]
    [PATCHES <patch1.patch> <patch2.patch>...]
)
```

## Parameters:
### OUT_SOURCE_PATH
Specifies the out-variable that will contain the extracted location.

This should be set to `SOURCE_PATH` by convention.

### URL
The url of the git repository.

### REF
The git sha of the commit to download.

### TAG
An optional git tag to be verified against the `REF`. If the remote repository's tag does not match the specified `REF`, the build will fail.

### PATCHES
A list of patches to be applied to the extracted sources.

Relative paths are based on the port directory.

### X_OUT_REF (internal only)
This parameter is used for automatic REF updates for certain ports in the central vcpkg catalog. It should not be used by any ports outside the central catalog and within the central catalog it should not be used on any user path. This parameter may change behavior incompatibly or be removed at any time.

## Notes:
`OUT_SOURCE_PATH`, `REF`, and `URL` must be specified.

## Examples:

* [fdlibm](https://github.com/Microsoft/vcpkg/blob/master/ports/fdlibm/portfile.cmake)
#]===]

include(vcpkg_execute_in_download_mode)

function(vcpkg_from_git)
  set(oneValueArgs OUT_SOURCE_PATH URL REF TAG X_OUT_REF)
  set(multipleValuesArgs PATCHES)
  # parse parameters such that semicolons in options arguments to COMMAND don't get erased
  cmake_parse_arguments(PARSE_ARGV 0 _vdud "" "${oneValueArgs}" "${multipleValuesArgs}")

  if(NOT DEFINED _vdud_OUT_SOURCE_PATH)
    message(FATAL_ERROR "OUT_SOURCE_PATH must be specified.")
  endif()

  if(NOT DEFINED _vdud_URL)
    message(FATAL_ERROR "The git url must be specified")
  endif()

  if(NOT DEFINED _vdud_REF)
    message(FATAL_ERROR "The git ref must be specified.")
  endif()

  if(NOT DEFINED _vdud_TAG)
    set(_vdud_TAG ${_vdud_REF})
  endif()
  
  # using .tar.gz instead of .zip because the hash of the latter is affected by timezone.
  string(REPLACE "/" "-" SANITIZED_REF "${_vdud_TAG}")
  set(TEMP_ARCHIVE "${DOWNLOADS}/temp/${PORT}-${SANITIZED_REF}.tar.gz")
  set(ARCHIVE "${DOWNLOADS}/${PORT}-${SANITIZED_REF}.tar.gz")
  set(TEMP_SOURCE_PATH "${CURRENT_BUILDTREES_DIR}/src/${SANITIZED_REF}")

  if(NOT EXISTS "${ARCHIVE}")
    if(_VCPKG_NO_DOWNLOADS)
        message(FATAL_ERROR "Downloads are disabled, but '${ARCHIVE}' does not exist.")
    endif()
    message(STATUS "Fetching ${_vdud_URL}...")
    find_program(GIT NAMES git git.cmd)
    # Note: git init is safe to run multiple times
    vcpkg_execute_required_process(
      ALLOW_IN_DOWNLOAD_MODE
      COMMAND ${GIT} init git-tmp
      WORKING_DIRECTORY ${DOWNLOADS}
      LOGNAME git-init-${TARGET_TRIPLET}
    )
    vcpkg_execute_required_process(
      ALLOW_IN_DOWNLOAD_MODE
      COMMAND ${GIT} fetch ${_vdud_URL} ${_vdud_TAG} --depth 1 -n
      WORKING_DIRECTORY ${DOWNLOADS}/git-tmp
      LOGNAME git-fetch-${TARGET_TRIPLET}
    )
    vcpkg_execute_in_download_mode(
      COMMAND ${GIT} rev-parse FETCH_HEAD
      OUTPUT_VARIABLE REV_PARSE_HEAD
      ERROR_VARIABLE REV_PARSE_HEAD
      RESULT_VARIABLE error_code
      WORKING_DIRECTORY ${DOWNLOADS}/git-tmp
    )
    if(error_code)
        message(FATAL_ERROR "unable to determine FETCH_HEAD after fetching git repository")
    endif()
    string(REGEX REPLACE "\n$" "" REV_PARSE_HEAD "${REV_PARSE_HEAD}")
    if(NOT REV_PARSE_HEAD STREQUAL _vdud_REF AND NOT DEFINED _vdud_X_OUT_REF)
        message(STATUS "[Expected : ( ${_vdud_REF} )]")
        message(STATUS "[  Actual : ( ${REV_PARSE_HEAD} )]")
        message(FATAL_ERROR "REF (${_vdud_REF}) does not match FETCH_HEAD (${REV_PARSE_HEAD})")
    elseif(DEFINED _vdud_X_OUT_REF)
        set(${_vdud_X_OUT_REF} ${REV_PARSE_HEAD} PARENT_SCOPE)
        return()
    endif()

    file(MAKE_DIRECTORY "${DOWNLOADS}/temp")
    vcpkg_execute_required_process(
      ALLOW_IN_DOWNLOAD_MODE
      COMMAND ${GIT} archive FETCH_HEAD -o "${TEMP_ARCHIVE}"
      WORKING_DIRECTORY ${DOWNLOADS}/git-tmp
      LOGNAME git-archive
    )

    get_filename_component(downloaded_file_dir "${ARCHIVE}" DIRECTORY)
    file(MAKE_DIRECTORY "${downloaded_file_dir}")
    file(RENAME "${TEMP_ARCHIVE}" "${ARCHIVE}")
  else()
    message(STATUS "Using cached ${ARCHIVE}")
  endif()

  vcpkg_extract_source_archive_ex(
    OUT_SOURCE_PATH SOURCE_PATH
    ARCHIVE "${ARCHIVE}"
    REF "${SANITIZED_REF}"
    PATCHES ${_vdud_PATCHES}
    NO_REMOVE_ONE_LEVEL
  )

  set(${_vdud_OUT_SOURCE_PATH} "${SOURCE_PATH}" PARENT_SCOPE)
endfunction()