1 # Copyright (C) 2002-2024 Free Software Foundation, Inc.
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation, either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16 from __future__
import annotations
18 #===============================================================================
19 # Define global imports
20 #===============================================================================
22 from .constants
import joinpath
23 from .GLConfig
import GLConfig
25 #===============================================================================
26 # Define GLMakefileTable class
27 #===============================================================================
28 class GLMakefileTable
:
29 '''This class is used to edit Makefile and store edits as table.
30 When user creates Makefile.am, he may need to use this class.
31 The internal representation consists of a list of edits.
32 Each edit is a dictionary with keys 'dir', 'var', 'val', 'dotfirst'.
33 An edit may be removed; this is done by removing its 'var' key but
34 keeping it in the list. Removed edits must be ignored.'''
37 table
: list[dict[str, str |
bool]]
39 def __init__(self
, config
: GLConfig
) -> None:
40 '''Create GLMakefileTable instance.'''
41 if type(config
) is not GLConfig
:
42 raise TypeError('config must be a GLConfig, not %s'
43 % type(config
).__name
__)
47 def __getitem__(self
, y
: int) -> dict[str, str |
bool]:
48 '''x.__getitem__(y) = x[y]'''
49 if type(y
) is not int:
50 raise TypeError('indices must be integers, not %s'
52 result
= self
.table
[y
]
53 # Do *not* clone the result here. We want GLEmiter to be able to make
54 # side effects on the result.
57 def editor(self
, dir: str, var
: str, val
: str, dotfirst
: bool = False) -> None:
58 '''This method is used to remember that ${dir}Makefile.am needs to be edited
59 to that ${var} mentions ${val}.
60 If ${dotfirst} is non-empty, this mention needs to be present after '.'.
61 This is a special hack for the SUBDIRS variable, cf.
62 <https://www.gnu.org/software/automake/manual/html_node/Subdirectories.html>.'''
63 if type(dir) is not str:
64 raise TypeError('dir must be a string, not %s' % (type(dir).__name
__))
65 if type(var
) is not str:
66 raise TypeError('var must be a string, not %s' % (type(var
).__name
__))
67 if type(val
) is not str:
68 raise TypeError('val must be a string, not %s' % (type(val
).__name
__))
69 if type(dotfirst
) is not bool:
70 raise TypeError('dotfirst must be a bool, not %s' % (type(dotfirst
).__name
__))
71 dictionary
= {'dir': dir, 'var': var
, 'val': val
, 'dotfirst': dotfirst
}
72 self
.table
.append(dictionary
)
74 def parent(self
, gentests
: bool, source_makefile_am
: str, tests_makefile_am
: str) -> None:
75 '''Add a special row to Makefile.am table with the first parent directory
76 which contains or will contain Makefile.am file.
77 GLConfig: sourcebase, m4base, testsbase, incl_test_categories,
78 excl_test_categories, makefile_name.
79 gentests is a bool that is True if any files are to be placed in $testsbase.
80 source_makefile_am is the name of the source Makefile.am.
81 tests_makefile_am is the name of the tests Makefile.am.'''
82 if type(gentests
) is not bool:
83 raise TypeError('gentests must be a bool, not %s' % (type(gentests
).__name
__))
84 if type(source_makefile_am
) is not str:
85 raise TypeError('source_makefile_am must be a str, not %s' % (type(source_makefile_am
).__name
__))
86 if type(tests_makefile_am
) is not str:
87 raise TypeError('tests_makefile_am must be a str, not %s' % (type(tests_makefile_am
).__name
__))
88 m4base
= self
.config
['m4base']
89 sourcebase
= self
.config
['sourcebase']
90 testsbase
= self
.config
['testsbase']
91 dir1
= '%s%s' % (m4base
, os
.path
.sep
)
94 and not (os
.path
.isfile(joinpath(self
.config
['destdir'], dir1
, 'Makefile.am'))
95 or joinpath(dir1
, 'Makefile.am') == joinpath(sourcebase
, source_makefile_am
)
96 or (gentests
and joinpath(dir1
, 'Makefile.am') == joinpath(testsbase
, tests_makefile_am
)))):
97 dir2
= joinpath(os
.path
.basename(dir1
), dir2
)
98 dir1
= os
.path
.dirname(dir1
)
99 self
.editor(dir1
, 'EXTRA_DIST', joinpath(dir2
, 'gnulib-cache.m4'))
101 def count(self
) -> int:
102 '''Count number of edits which are stored, including the removed ones.'''
103 return len(self
.table
)