Changeset View
Standalone View
modules/ECMSourceVersionControl.cmake
Context not available. | |||||
2 | # ECMSourceVersionControl | 2 | # ECMSourceVersionControl | ||
---|---|---|---|---|---|
3 | # -------------------------- | 3 | # -------------------------- | ||
4 | # | 4 | # | ||
5 | # Tries to determine whether the source is under version control (git clone, | 5 | # This module allows to determine if and through which of the known version | ||
6 | # svn checkout, etc). | 6 | # control systems the source directory is controlled: | ||
7 | # | ||||
8 | # * ``ECM_SOURCE_UNDER_VERSION_CONTROL`` is set to ``TRUE`` when indication | ||||
9 | # is found that ``CMAKE_SOURCE_DIR`` is under version control, else set to | ||||
10 | # ``FALSE``. | ||||
11 | # * ``ECM_SOURCE_VERSION_CONTROL_WHICH`` will be set to any of the following | ||||
12 | # strings in case ``ECM_SOURCE_UNDER_VERSION_CONTROL`` is ``TRUE``: | ||||
13 | # ``git`` in case the source directory is controlled by Git (i.e. it is a | ||||
14 | # Git clone), ``svn`` for Subversion, ``hg`` for Mercurial, and ``bzr`` for | ||||
15 | # Bazaar. | ||||
16 | # | ||||
17 | # Above variables will be automatically set once this module is loaded. | ||||
18 | # Determining the variables' values is considered a cheap operation as it only | ||||
19 | # requires probing the filesystem for the existance of certain directories. | ||||
20 | # | ||||
21 | # In case Git is used for version control, additional functions are available | ||||
22 | # to retrieve more detailed information about the local checkout's state. | ||||
23 | # However, as those functions will invoke the ``git`` binary internally which | ||||
24 | # then may perform complex operations, those function invocations are to be | ||||
25 | # considered 'expensive'. | ||||
26 | # | ||||
27 | # The following function will invoke Git to retrieve the current revision as | ||||
28 | # represented by the first eight hexdecimal characters of the current commit's | ||||
29 | # SHA1 identifier. The revision will be stored in <variable>. | ||||
30 | # | ||||
31 | # :: | ||||
32 | # | ||||
33 | # ecm_source_version_control_probe_revision(<variable>) | ||||
34 | # | ||||
35 | # Similar to above function, the following function will invoke Git to retrieve | ||||
36 | # the current branch's name (for example, 'master'). The branch's name will be | ||||
37 | # stored in <variable>. | ||||
38 | # | ||||
39 | # :: | ||||
40 | # | ||||
41 | # ecm_source_version_control_probe_branch(<variable>) | ||||
42 | # | ||||
43 | # Only if there is an issue, such as being invoked on a source directory that is | ||||
44 | # not managed with Git, above functions will print messages (warnings). | ||||
45 | # To get a 'friendly' output during the configuration phase and only if the | ||||
46 | # source code is actually version controlled via Git, the following function | ||||
47 | # will issue an informative message about the Git checkout's revision and | ||||
48 | # branch. Internally, it makes use of both functions discussed above. | ||||
49 | # | ||||
50 | # :: | ||||
51 | # | ||||
52 | # ecm_source_version_control_status() | ||||
7 | # | 53 | # | ||
8 | # ``ECM_SOURCE_UNDER_VERSION_CONTROL`` is set when indication is found that | | |||
9 | # CMAKE_SOURCE_DIR is under version control. | | |||
10 | # | 54 | # | ||
11 | # Since 5.63 | 55 | # Since 5.63 | ||
12 | 56 | | |||
13 | #============================================================================= | 57 | #============================================================================= | ||
14 | # Copyright 2019 Harald Sitter <sitter@kde.org> | 58 | # Copyright 2019 Harald Sitter <sitter@kde.org> | ||
59 | # Copyright 2019 Thomas Fischer <fischer@unix-ag.uni-kl.de> | ||||
15 | # | 60 | # | ||
16 | # Redistribution and use in source and binary forms, with or without | 61 | # Redistribution and use in source and binary forms, with or without | ||
sitter: Do we really need this? It seems to me we could just spam it for every call, in the grand… | |||||
17 | # modification, are permitted provided that the following conditions | 62 | # modification, are permitted provided that the following conditions | ||
I think you are leaking this variable into the parent scope. I am not super sure how to deal with this but I think I've seen _prefixes, or you use a function and explicitly forward into the PARENT_SCOPE (https://cmake.org/cmake/help/v3.0/command/set.html). Alternatively with a multi-function approach I'd probably just make it ECM_SOURCE_VERSION_CONTROL_EXECUTABLE so it only needs finding on the first call. sitter: I think you are leaking this variable into the parent scope. I am not super sure how to deal… | |||||
I'd move the exec detection and missing reporting into its own helper which gets called by all "public" functions. Currently the logic is duped in both functions. sitter: I'd move the exec detection and missing reporting into its own helper which gets called by all… | |||||
Context not available. | |||||
36 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 81 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
37 | # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 82 | # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
38 | 83 | | |||
39 | if(EXISTS "${CMAKE_SOURCE_DIR}/.git" OR | 84 | if(EXISTS "${CMAKE_SOURCE_DIR}/.git") | ||
40 | EXISTS "${CMAKE_SOURCE_DIR}/.svn" OR | 85 | # Git | ||
41 | EXISTS "${CMAKE_SOURCE_DIR}/.hg" OR | 86 | set(ECM_SOURCE_UNDER_VERSION_CONTROL TRUE) | ||
42 | EXISTS "${CMAKE_SOURCE_DIR}/.bzr") | 87 | set(ECM_SOURCE_VERSION_CONTROL_WHICH "git") | ||
I think it's more idiomatic if you accept the variable name as a function argument instead of hardcoding one. For example find_program, but really most helpers work like that off the top of my head. sitter: I think it's more idiomatic if you accept the variable name as a function argument instead of… | |||||
88 | elseif(EXISTS "${CMAKE_SOURCE_DIR}/.svn") | ||||
89 | # Subversion | ||||
90 | set(ECM_SOURCE_UNDER_VERSION_CONTROL TRUE) | ||||
91 | set(ECM_SOURCE_VERSION_CONTROL_WHICH "svn") | ||||
92 | elseif(EXISTS "${CMAKE_SOURCE_DIR}/.hg") | ||||
93 | # Mercurial | ||||
94 | set(ECM_SOURCE_UNDER_VERSION_CONTROL TRUE) | ||||
95 | set(ECM_SOURCE_VERSION_CONTROL_WHICH "hg") | ||||
96 | elseif(EXISTS "${CMAKE_SOURCE_DIR}/.bzr") | ||||
97 | # Bazaar | ||||
43 | set(ECM_SOURCE_UNDER_VERSION_CONTROL TRUE) | 98 | set(ECM_SOURCE_UNDER_VERSION_CONTROL TRUE) | ||
99 | set(ECM_SOURCE_VERSION_CONTROL_WHICH "bzr") | ||||
44 | else() | 100 | else() | ||
101 | unset(ECM_SOURCE_VERSION_CONTROL_WHICH) | ||||
45 | set(ECM_SOURCE_UNDER_VERSION_CONTROL FALSE) | 102 | set(ECM_SOURCE_UNDER_VERSION_CONTROL FALSE) | ||
46 | endif() | 103 | endif() | ||
104 | | ||||
105 | function(_ecm_source_version_control_detect_git) | ||||
106 | if(NOT _ECM_SOURCE_VERSION_GIT_EXECUTABLE) | ||||
107 | find_program(_ECM_SOURCE_VERSION_GIT_EXECUTABLE | ||||
108 | NAMES git.bat git # for Windows, 'git.bat' must be found before 'git' | ||||
109 | ) | ||||
110 | endif() | ||||
111 | if(NOT _ECM_SOURCE_VERSION_GIT_EXECUTABLE) | ||||
112 | message(WARNING "No Git executable found despite .git directory located in source directory") | ||||
113 | endif() | ||||
114 | endfunction() | ||||
115 | | ||||
116 | function(ecm_source_version_control_probe_revision outvar) | ||||
117 | if(NOT ${ECM_SOURCE_UNDER_VERSION_CONTROL}) | ||||
118 | message("Source directory not managed by a known version control system") | ||||
119 | elseif(${ECM_SOURCE_VERSION_CONTROL_WHICH} STREQUAL "git") | ||||
120 | # Git | ||||
121 | _ecm_source_version_control_detect_git() | ||||
122 | if(_ECM_SOURCE_VERSION_GIT_EXECUTABLE) | ||||
123 | execute_process( | ||||
124 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" | ||||
125 | COMMAND "${_ECM_SOURCE_VERSION_GIT_EXECUTABLE}" rev-parse --short HEAD | ||||
126 | OUTPUT_VARIABLE ECM_SOURCE_VERSION_CONTROL_REVISION | ||||
127 | OUTPUT_STRIP_TRAILING_WHITESPACE | ||||
128 | ) | ||||
129 | set(${outvar} ${ECM_SOURCE_VERSION_CONTROL_REVISION} PARENT_SCOPE) | ||||
130 | endif() | ||||
131 | else() | ||||
132 | message(WARNING "Source directory not managed by a supported version control system (Git)") | ||||
133 | endif() | ||||
134 | endfunction() | ||||
135 | | ||||
136 | function(ecm_source_version_control_probe_branch outvar) | ||||
137 | if(NOT ${ECM_SOURCE_UNDER_VERSION_CONTROL}) | ||||
138 | message("Source directory not managed by a known version control system") | ||||
139 | elseif(${ECM_SOURCE_VERSION_CONTROL_WHICH} STREQUAL "git") | ||||
140 | # Git | ||||
141 | _ecm_source_version_control_detect_git() | ||||
142 | if(_ECM_SOURCE_VERSION_GIT_EXECUTABLE) | ||||
143 | execute_process( | ||||
144 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" | ||||
145 | COMMAND "${_ECM_SOURCE_VERSION_GIT_EXECUTABLE}" rev-parse --abbrev-ref HEAD | ||||
146 | OUTPUT_VARIABLE ECM_SOURCE_VERSION_CONTROL_BRANCH | ||||
147 | OUTPUT_STRIP_TRAILING_WHITESPACE | ||||
148 | ) | ||||
149 | set(${outvar} ${ECM_SOURCE_VERSION_CONTROL_BRANCH} PARENT_SCOPE) | ||||
150 | endif() | ||||
151 | else() | ||||
152 | message(WARNING "Source directory not managed by a supported version control system (Git)") | ||||
153 | endif() | ||||
154 | endfunction() | ||||
155 | | ||||
156 | function(ecm_source_version_control_status) | ||||
157 | if(${ECM_SOURCE_UNDER_VERSION_CONTROL} AND "${ECM_SOURCE_VERSION_CONTROL_WHICH}" STREQUAL "git") | ||||
158 | message(STATUS "Source directory '${CMAKE_SOURCE_DIR}' is under version control by Git.") | ||||
159 | ecm_source_version_control_probe_revision(ECM_SOURCE_VERSION_CONTROL_REVISION) | ||||
160 | ecm_source_version_control_probe_branch(ECM_SOURCE_VERSION_CONTROL_BRANCH) | ||||
161 | if(ECM_SOURCE_VERSION_CONTROL_REVISION AND ECM_SOURCE_VERSION_CONTROL_BRANCH) | ||||
162 | message(STATUS "The current Git checkout is branch '${ECM_SOURCE_VERSION_CONTROL_BRANCH}' at commit ${ECM_SOURCE_VERSION_CONTROL_REVISION}.") | ||||
163 | endif() | ||||
164 | endif() | ||||
165 | endfunction() | ||||
Context not available. |
Do we really need this? It seems to me we could just spam it for every call, in the grand scheme of things it makes no difference but is less logic one has to worry about when extending this module.