comparison scripts/miscellaneous/license.m @ 19237:6dfce51a7b40

license.m: update to treat packages as features (bug #43154). * miscellaneous/license.m: this function was originally written when the only feature was a monolithic installation of Octave Forge. This cset updates it to treat packages as features. It also disables the TOOGLE option which does not make any sense in the context of free software.
author Carnë Draug <carandraug@octave.org>
date Mon, 29 Sep 2014 00:29:32 +0100
parents d63878346099
children 672674d5e8d9
comparison
equal deleted inserted replaced
19236:4871d0ecbfa7 19237:6dfce51a7b40
1 ## Copyright (C) 2005-2013 William Poetra Yoga Hadisoeseno 1 ## Copyright (C) 2005-2013 William Poetra Yoga Hadisoeseno
2 ## Copyright (C) 2014 Carnë Draug
2 ## 3 ##
3 ## This file is part of Octave. 4 ## This file is part of Octave.
4 ## 5 ##
5 ## Octave is free software; you can redistribute it and/or modify it 6 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by 7 ## under the terms of the GNU General Public License as published by
16 ## along with Octave; see the file COPYING. If not, see 17 ## along with Octave; see the file COPYING. If not, see
17 ## <http://www.gnu.org/licenses/>. 18 ## <http://www.gnu.org/licenses/>.
18 19
19 ## -*- texinfo -*- 20 ## -*- texinfo -*-
20 ## @deftypefn {Command} {} license 21 ## @deftypefn {Command} {} license
22 ## @deftypefnx {Command} {} license inuse
23 ## @deftypefnx {Command} {} license inuse @var{feature}
21 ## @deftypefnx {Function File} {} license ("inuse") 24 ## @deftypefnx {Function File} {} license ("inuse")
22 ## @deftypefnx {Function File} {@var{retval} =} license ("inuse") 25 ## @deftypefnx {Function File} {@var{retval} =} license ("inuse")
23 ## @deftypefnx {Function File} {@var{retval} =} license ("test", @var{feature}) 26 ## @deftypefnx {Function File} {@var{retval} =} license ("test", @var{feature})
24 ## @deftypefnx {Function File} {} license ("test", @var{feature}, @var{toggle})
25 ## @deftypefnx {Function File} {@var{retval} =} license ("checkout", @var{feature}) 27 ## @deftypefnx {Function File} {@var{retval} =} license ("checkout", @var{feature})
26 ## 28 ## @deftypefnx {Function File} {[@var{retval}, @var{errmsg}] =} license ("checkout", @var{feature})
27 ## Display the license of Octave. 29 ## Get license information for Octave and Octave packages.
28 ## 30 ##
29 ## @code{license ("inuse")} 31 ## GNU Octave is free software distributed under the GNU General Public
32 ## License (GPL), and a license manager makes no sense. This function is
33 ## provided only for @sc{Matlab} compatibility.
30 ## 34 ##
31 ## Display a list of packages currently being used. 35 ## When called with no extra input arguments, it returns the Octave license,
32 ## 36 ## otherwise the first input defines the operation mode and must be one of
33 ## @code{@var{retval} = license ("inuse")} 37 ## the following strings: @code{inuse}, @code{test}, and @code{checkout}.
34 ## 38 ## The optional @var{feature} argument can either be @qcode{"octave"} (core),
35 ## Return a structure containing the fields @code{feature} and @code{user}. 39 ## or an Octave package.
36 ##
37 ## @code{@var{retval} = license ("test", @var{feature})}
38 ##
39 ## Return 1 if a license exists for the product identified by the string
40 ## @var{feature} and 0 otherwise. The argument @var{feature} is case
41 ## insensitive and only the first 27 characters are checked.
42 ##
43 ## @code{license ("test", @var{feature}, @var{toggle})}
44 ##
45 ## Enable or disable license testing for @var{feature}, depending on
46 ## @var{toggle}, which may be one of:
47 ## 40 ##
48 ## @table @asis 41 ## @table @asis
49 ## @item @qcode{"enable"} 42 ## @item @qcode{"inuse"}
50 ## Future tests for the specified license of @var{feature} are conducted 43 ## Returns a list of loaded features, i.e., octave and the list of loaded
51 ## as usual. 44 ## packages. If an output is requested, it returns a struct array with
45 ## the fields @qcode{"feature"}, and @qcode{"user"}.
52 ## 46 ##
53 ## @item @qcode{"disable"} 47 ## @item @qcode{"test"}
54 ## Future tests for the specified license of @var{feature} return 0. 48 ## Return true if the specified @var{feature} is installed, false otherwise.
49 ##
50 ## An optional third argument @qcode{"enable"} or @qcode{"disable"} is
51 ## accepted but ignored.
52 ##
53 ## @item @qcode{"checkout"}
54 ## Return true if the specified @var{feature} is installed, false otherwise.
55 ## An optional second output will have an error message if a package is not
56 ## installed.
57 ##
55 ## @end table 58 ## @end table
56 ## 59 ##
57 ## @code{@var{retval} = license ("checkout", @var{feature})} 60 ## @seealso{pkg, ver, version}
58 ##
59 ## Check out a license for @var{feature}, returning 1 on success and 0
60 ## on failure.
61 ##
62 ## This function is provided for compatibility with @sc{matlab}.
63 ## @seealso{ver, version}
64 ## @end deftypefn 61 ## @end deftypefn
65 62
66 ## Author: William Poetra Yoga Hadisoeseno <williampoetra@gmail.com> 63 ## Author: William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
67 64
68 function retval = license (varargin) 65 function [retval, errmsg] = license (cmd, feature, toogle)
69 66
70 persistent __octave_licenses__; 67 if (nargin > 3)
71
72 if (isempty (__octave_licenses__))
73 __octave_licenses__ = cell ();
74 __octave_licenses__{1,1} = "Octave";
75 __octave_licenses__{1,2} = "GNU General Public License";
76 __octave_licenses__{1,3} = true;
77 if (exist ("OCTAVE_FORGE_VERSION"))
78 __octave_licenses__{2,1} = "octave-forge";
79 __octave_licenses__{2,2} = "<various licenses>";
80 __octave_licenses__{2,3} = true;
81 endif
82 endif
83
84 nout = nargout;
85 nin = nargin;
86 nr_licenses = rows (__octave_licenses__);
87
88 if (nout > 1 || nin > 3)
89 print_usage (); 68 print_usage ();
90 endif 69 endif
91 70
92 if (nin == 0) 71 ## Then only give information about Octave core
72 if (nargin == 0)
73 retval = "GNU General Public License";
74 return
75 endif
93 76
94 found = find (strcmp (__octave_licenses__(:,1), "Octave"), 1); 77 [features, desc, flags] = get_all_features ();
95 78
96 if (! isempty (found)) 79 switch tolower (cmd)
97 result = __octave_licenses__{found,2}; 80 case "inuse"
98 else 81 if (nargin > 2)
99 result = "unknown"; 82 print_usage ();
100 endif
101
102 if (nout == 0)
103 printf ("%s\n", result);
104 else
105 retval = result;
106 endif
107
108 elseif (nin == 1)
109
110 if (nout == 0)
111
112 if (! strcmp (varargin{1}, "inuse"))
113 usage ('license ("inuse")');
114 endif 83 endif
115 84
116 printf ("%s\n", __octave_licenses__{:,1}); 85 unloaded = cellfun (@(x) x.name, desc(strcmpi (flags, "Not loaded")),
86 "UniformOutput", false);
87 features(ismember (features, unloaded)) = [];
117 88
118 else 89 if (nargin > 1)
119 90 features = features(strcmp (features, feature));
120 if (! strcmp (varargin{1}, "inuse")) 91 endif
121 usage ('retval = license ("inuse")'); 92 if (nargout == 0)
93 printf ("%s\n", features{:});
94 else
95 retval = struct ("feature", features, "user", get_username ());
122 endif 96 endif
123 97
124 pw = getpwuid (getuid ()); 98 case "test"
125 if (isstruct (pw)) 99 if (nargin < 2)
126 username = pw.name; 100 print_usage ();
127 else
128 username = "octave_user";
129 endif 101 endif
130 102
131 retval = struct ("feature", __octave_licenses__(:,1), "user", username); 103 if (nargin > 2)
132 104 ## We ignore the toogle argument because... what's the point? We
133 endif 105 ## don't need a license management system on Octave. This function
134 106 ## will return true, even if anyone tries to disabled a license.
135 else 107 switch tolower (toogle)
136 108 case "enable", # do nothing
137 feature = varargin{2}(1:(min ([(length (varargin{2})), 27]))); 109 case "disable", # do nothing
138 110 otherwise, error ("license: TOOGLE must be enable or disable");
139 if (strcmp (varargin{1}, "test")) 111 endswitch
140
141 found = find (strcmpi (__octave_licenses__(:,1), feature), 1);
142
143 if (nin == 2)
144 retval = ! isempty (found) && __octave_licenses__{found,3};
145 else
146 if (! isempty (found))
147 if (strcmp (varargin{3}, "enable"))
148 __octave_licenses__{found,3} = true;
149 elseif (strcmp (varargin{3}, "disable"))
150 __octave_licenses__{found,3} = false;
151 else
152 error ("license: TOGGLE must be either 'enable' or 'disable'");
153 endif
154 else
155 error ("license: FEATURE '%s' not found", feature);
156 endif
157 endif 112 endif
158 113
159 elseif (strcmp (varargin{1}, "checkout")) 114 retval = any (strcmp (features, feature));
160 115
161 if (nin != 2) 116 case "checkout"
162 usage ('retval = license ("checkout", feature)'); 117 ## I guess we could have the checkout command load packages but it's not
118 ## really the same thing. The closest we have is simply to check if
119 ## there is a package with the feature name, and give an error if not.
120
121 if (nargin != 2)
122 print_usage ();
163 endif 123 endif
164 124
165 found = find (strcmpi (__octave_licenses__(:,1), feature), 1); 125 retval = any (strcmp (features, feature));
126 errmsg = "";
166 127
167 retval = ! isempty (found) && __octave_licenses__{found,3}; 128 if (! retval)
129 errmsg = ["No package named \"" feature "\" installed"];
130 endif
168 131
169 else 132 otherwise
170 print_usage (); 133 print_usage ();
171 endif 134 endswitch
172
173 endif
174 135
175 endfunction 136 endfunction
176 137
138 function username = get_username ()
139 pw = getpwuid (getuid ());
140 if (isstruct (pw))
141 username = pw.name;
142 else
143 username = "octave_user";
144 endif
145 endfunction
177 146
178 %!assert (license(), "GNU General Public License") 147 function [features, desc, loaded] = get_all_features ()
179 %!assert ((license ("inuse")).feature, "Octave") 148 [desc, loaded] = pkg ("describe", "all");
149 pkg_names = cellfun (@(x) x.name, desc, "UniformOutput", false);
150 features = {"octave", pkg_names{:}};
151 endfunction
152
153 %!assert (license (), "GNU General Public License")
154 %!assert ((license ("inuse", "octave")).feature, "octave")
180 155
181 %!test 156 %!test
182 %! lstate = license ("test", "Octave"); 157 %! [desc, flags] = pkg ("describe", "all");
183 %! license ("test", "Octave", "disable"); 158 %! for idx = 1: numel (desc)
184 %! assert (license ("test", "Octave"), false); 159 %! name = desc{idx}.name;
185 %! license ("test", "Octave", "enable"); 160 %! switch (flags{idx})
186 %! assert (license ("test", "Octave"), true); 161 %! case "Loaded"
187 %! if (lstate == false) 162 %! assert ((license ("inuse", name)).feature, name);
188 %! license ("test", "Octave", "disable"); 163 %! case "Not loaded"
189 %! endif 164 %! rv = license ("inuse", name);
165 %! assert (isstruct (rv));
166 %! assert (all (ismember ({"feature", "user"}, fieldnames (rv))));
167 %! otherwise
168 %! error ("code in license out of date");
169 %! endswitch
170 %! endfor
190 171
191 %!assert (license ("checkout", "Octave"), true) 172 %!assert (license ("test", "octave"), true)
173 %!assert (license ("test", "not_a_valid package name"), false)
174
175 %!test
176 %! desc = pkg ("describe", "all");
177 %! for idx = 1: numel (desc)
178 %! assert (license ("test", desc{idx}.name), true)
179 %! endfor
180
181 %!assert (license ("checkout", "octave"), true)
182
183 %!test
184 %! [s, e] = license ("checkout", "NOT_A_PACKAGE");
185 %! assert (e, "No package named \"NOT_A_PACKAGE\" installed");
192 186
193 %% Test input validation 187 %% Test input validation
194 %!error license ("not_inuse") 188 %!error license ("not_inuse")
195 %!error <TOGGLE must be either> license ("test", "Octave", "not_enable") 189 %!error license ("not_test", "octave", "enable")
196 %!error <FEATURE 'INVALID' not found> license ("test", "INVALID", "enable") 190 %!error <TOOGLE must be enable or disable> license ("test", "octave", "invalid_toogle")
197 %!error license ("not_test", "Octave", "enable")
198 191