]> andersk Git - moira.git/blob - clients/moira/menus.c
added GetFSM
[moira.git] / clients / moira / menus.c
1 #if (!defined(lint) && !defined(SABER))
2   static char rcsid_module_c[] = "$Header$";
3 #endif lint
4
5 /*      This is the file menus.c for the MOIRA Client, which allows a nieve
6  *      user to quickly and easily maintain most parts of the MOIRA database.
7  *      It Contains: All menu definitions.
8  *      
9  *      Created:        4/11/88
10  *      By:             Chris D. Peterson
11  *
12  *      $Source$
13  *      $Author$
14  *      $Header$
15  *      
16  *      Copyright 1988 by the Massachusetts Institute of Technology.
17  *
18  *      For further information on copyright and distribution 
19  *      see the file mit-copyright.h
20  */
21
22 #include <stdio.h>
23 #include <menu.h>
24
25 #include "mit-copyright.h"
26 #include "defs.h"
27 #include "f_defs.h"
28 #include "globals.h"
29
30
31 /* ------------------------- Second Tier Menus ------------------------- */
32
33 /* 
34  * Cluster Data Menu
35  */
36
37 Menu cluster_data_menu = {
38   NULLFUNC,
39   NULLFUNC,
40   "Cluster Data Menu",
41   4,
42   {
43     { ShowClusterData, NULLMENU, 3, {
44       {"show", "Show Data on a given Cluster"},
45       {"clus", "Cluster's Name: "},
46       {"label", "Label Identifing the data: "},
47     } },
48     { AddClusterData, NULLMENU, 4, {
49       {"add", "Add Data to a given Cluster"},
50       {"clus", "Cluster Name: "},
51       {"label", "Label Identifing the data: "},
52       {"data", "The data to be added: "},
53     } },
54     { RemoveClusterData, NULLMENU, 3, {
55       {"delete", "Remove Data from a given Cluster"},
56       {"clus", "Cluster's Name: "},
57       {"label", "Label Identifing the data: "},
58     } }, 
59     SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode)
60   }
61 };
62
63 /*
64  * List Information Menu
65  */
66
67 Menu list_info_menu = {
68     NULLFUNC,
69     NULLFUNC,
70     "List Information Menu",
71     5,
72     {
73         SIMPLEFUNC("member",
74                    "Show all lists to which a given member belongs",
75                    ListByMember),
76         SIMPLEFUNC("admin",
77                    "Show all items which a given member can administer",
78                    ListByAdministrator),
79         SIMPLEFUNC("groups", "Show all lists which are groups",
80                    ListAllGroups),
81         SIMPLEFUNC("public", "Show all public mailing lists",
82                    ListAllPublicMailLists),
83         SIMPLEFUNC("maillists", "Show all mailing lists",
84                    ListAllMailLists)
85     }
86 };
87
88 /*
89  * List Member Menu
90  */
91
92 Menu list_member_menu = {
93     ListmaintMemberMenuEntry,
94     ListmaintMemberMenuExit,
95     NULL,
96     7,
97     {
98         SIMPLEFUNC("add", "Add a member to this list", AddMember),
99         SIMPLEFUNC("remove", "Remove a member from this list", DeleteMember),
100         SIMPLEFUNC("all", "Show the members of this list", ListAllMembers),
101         SIMPLEFUNC("user", "Show the members of type USER", ListUserMembers),
102         SIMPLEFUNC("list", "Show the members of type LIST", ListListMembers),
103         SIMPLEFUNC("string", "Show the members of type STRING", 
104                    ListStringMembers),
105         SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode)
106     } 
107 };
108
109 /*
110  *  Machine To Cluster Mappings Menu
111  */
112
113 Menu mappings_menu = {
114   NULLFUNC,
115   NULLFUNC,
116   "Machine To Cluster Mappings Menu",
117   4,
118   {
119     { MachineToClusterMap, NULLMENU, 3, {
120       {"map", "Show Machine to cluster mapping"},
121       {"name", "Machine's Name: "},
122       {"cluster", "Cluster's Name: "},
123     } },
124     { AddMachineToCluster, NULLMENU, 3, {
125       {"addcluster","Add machines to a clusters"},
126       {"name","Machine's Name: "},
127       {"cluster", "Cluster's Name: "},
128     } },
129     { RemoveMachineFromCluster, NULLMENU, 3, {
130       {"remcluster", "Remove machines from clusters"},
131       {"name","Machine's Name: "},
132       {"cluster", "Cluster's Name: "},
133     } },
134     SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode),
135   }
136 };
137
138 /* 
139  * Post Office Box Menu
140  */
141
142 Menu pobox_menu = {
143   NULLFUNC,
144   NULLFUNC,
145   "Post Office Box Menu",
146   4,
147   {
148     {GetUserPOBox, NULLMENU, 2, {
149       {"show", "Show a user's post office box"},
150       {"login name", "login name: "}
151     } },
152     {SetUserPOBox, NULLMENU, 2, {
153       {"set", "Set (Add or Change) a user's post office box"},
154       {"login name", "login name: "}
155     } },
156     {RemoveUserPOBox, NULLMENU, 2, {
157       {"remove", "Remove a user's post office box"},
158       {"login name", "login name: "}
159     } },
160     SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode)
161   }
162 };
163    
164 /*
165  * Quota Menu
166  */
167  
168 Menu quota_menu = {
169   NULLFUNC,
170   NULLFUNC,
171   "Quota Menu",
172   8,
173   {
174     SIMPLEFUNC("shdef", "Show default user quota (in KB)", ShowDefaultQuota),
175     {ChangeDefaultQuota, NULLMENU, 2, {
176       {"chdef", "Change default user quota"},
177       {"quota", "New quota (in KB): "}
178     } },
179     SIMPLEFUNC("getquota", "Show a quota on a filesystem",
180                GetQuota),
181     SIMPLEFUNC("getfsquotas", "Show all quotas on a filesystem",
182                GetQuotaByFilesys),
183     SIMPLEFUNC("addquota", "Add a new disk quota on a filesystem",
184                AddQuota),
185     SIMPLEFUNC("upquota", "Change a quota on a filesystem",
186                UpdateQuota),
187     SIMPLEFUNC("delquota", "Delete a quota on a filesystem",
188                DeleteQuota),
189     SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode)
190   } 
191 };
192
193 Menu fsgroup_menu = {
194     NULLFUNC,
195     NULLFUNC,
196     "Filesystem Group Menu",
197     6,
198     {
199         { GetFS, NULLMENU, 2, {
200             {"get", "Get individual or group filesystem information"},
201             {"name", "Name of Filesystem: "}
202         } },
203         { AddFSToGroup, NULLMENU, 3, {
204             {"add", "Add a new filesystem to an FS group"},
205             {"group", "FS Group name: "},
206             {"filsys", "Filesystem name: "}
207         } },
208         { RemoveFSFromGroup, NULLMENU, 3, {
209             {"remove", "Remove a filesystem from an FS group"},
210             {"group", "FS Group name: "},
211             {"filsys", "Filesystem name: "}
212         } },
213         { ChangeFSGroupOrder, NULLMENU, 2, {
214             {"order", "Change the order of filesystems in a group"},
215             {"group", "FS Group name: "}
216         } },
217         SIMPLEFUNC("help", "Info on Filesystem Groups", FSGroupHelp),
218         SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode)
219     }
220 };
221
222 Menu service_menu = {
223     NULLFUNC,
224     NULLFUNC,
225     "DCM Service Menu",
226     6,
227     {
228         { showserv, NULLMENU, 2, {
229             { "showserv", "Show service information" },
230             { "service name", "Name of service: " },
231         } },
232         { addserv, NULLMENU, 2, {
233             { "addserv", "Add a new service" },
234             { "service name", "Name of service: " },
235         } },
236         { updateserv, NULLMENU, 2, {
237             { "updateserv", "Update service information" },
238             { "service name", "Name of service: " },
239         } },
240         { resetsrverr, NULLMENU, 2, {
241             { "resetsrverr", "Reset service error" },
242             { "service name", "Name of service: " },
243         } },
244         { resetsrvc, NULLMENU, 2, {
245             { "resetsrvc", "Reset service state" },
246             { "service name", "Name of service: " },
247         } },
248         { delserv, NULLMENU, 2, {
249             { "delserv", "Delete service info" },
250             { "service name", "Name of service: " },
251         } },
252     }
253 };
254
255 Menu host_menu = {
256     NULLFUNC,
257     NULLFUNC,
258     "DCM Host Menu",
259     7,
260     {
261         { showhost, NULLMENU, 3, {
262             { "showhost", "Show service/host tuple information" },
263             { "service name", "Name of service: " },
264             { "host name", "Name of machine: " },
265         } },
266         { addhost, NULLMENU, 3, {
267             { "addhost", "Add a new service/host tuple" },
268             { "service name", "Name of service: " },
269             { "host name", "Name of machine: " },
270         } },
271         { updatehost, NULLMENU, 3, {
272             { "updatehost", "Update a service/host tuple" },
273             { "service name", "Name of service: " },
274             { "host name", "Name of machine: " },
275         } },
276         { resethosterr, NULLMENU, 3, {
277             { "resethosterr", "Reset service/host error" },
278             { "service name", "Name of service: " },
279             { "host name", "Name of machine: " },
280         } },
281         { resethost, NULLMENU, 3, {
282             { "resethost", "Reset service/host state" },
283             { "service name", "Name of service: " },
284             { "host name", "Name of machine: " },
285         } },
286         { sethostor, NULLMENU, 3, {
287             { "override", "Set service/host override" },
288             { "service name", "Name of service: " },
289             { "host name", "Name of machine: " },
290         } },
291         { delhost, NULLMENU, 3, {
292             { "delhost", "Delete service/host tuple" },
293             { "service name", "Name of service: " },
294             { "host name", "Name of machine: " },
295         } },
296     }
297 };
298
299 /* ------------------------- First Tier Menus ------------------------- */
300
301 /* 
302  * Cluster Menu
303  */
304
305 Menu cluster_menu = {
306   NULLFUNC,
307   NULLFUNC,
308   "Cluster Menu",
309   7,
310   {
311     { ShowClusterInfo, NULLMENU, 2, {
312       {"show", "Get cluster information"},
313       {"name", "Cluster's Name: "}
314     } },
315     { AddCluster, NULLMENU, 2, {
316       {"add", "Add a new cluster"},
317       {"name","Cluster's Name: "},
318     } },
319     { UpdateCluster, NULLMENU, 2, {
320       {"update", "Update cluster information"},
321       {"name","Cluster's Name: "},
322     } },
323     { DeleteCluster, NULLMENU, 2, {
324       {"delete", "Delete this cluster"},
325       {"name", "Cluster's Name: "}
326     } },
327     SUBMENU("mappings","Machine To Cluster Mappings Menu", &mappings_menu),
328     SUBMENU("c_data","Cluster Data Menu", &cluster_data_menu),
329     SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode)
330   }
331 };
332
333 /* 
334  * Filesystem Menu
335  */
336
337 Menu filesys_menu = {
338   NULLFUNC, 
339   NULLFUNC, 
340   "Filesystem Menu",
341   10,
342   {
343     { GetFS, NULLMENU, 2, {
344       {"get", "Get Filesystem Name Information"},
345       {"name", "Name of Filesystem: "}
346     } },
347     { GetFSM, NULLMENU, 2, {
348       {"getmach", "Get Filesystems by Machine"},
349       {"name", "Name of Server: "}
350     } },
351     { AddFS, NULLMENU, 2, {
352       {"add", "Add New Filesystem to Database"},
353       {"name", "name: "},
354     } },
355     { ChangeFS, NULLMENU, 2, {
356       {"change", "Update Filesystem Information"},
357       {"name", "name: "},
358     } },
359     { DeleteFS, NULLMENU, 2, {
360       {"delete", "Delete Filesystem"},
361       {"name", "Filesystem Name: "}
362     } },
363     SUBMENU("fsgroups", "File System Groups Menu", &fsgroup_menu),
364     { GetFSAlias, NULLMENU, 2, {
365       {"check", "Check An Association"},
366       {"name", "alias name : "}
367     } },
368     { CreateFSAlias, NULLMENU, 2, {
369       {"alias", "Associate with a Filesystem"},
370       {"name", "alias name : "},
371     } },
372     { DeleteFSAlias, NULLMENU, 2, {
373       {"unalias", "Disassociate from a Filesystem"},
374       {"name", "alias name : "},
375     } },
376     SUBMENU("quotas","Quota Menu", &quota_menu),
377 /*    SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode), */
378 /*    SIMPLEFUNC("help", "Help ..", AttachHelp) */
379   }
380 };
381
382 /*
383  * Machine Menu
384  */
385
386 Menu machine_menu = {
387   NULLFUNC,
388   NULLFUNC,
389   "Machine Menu",
390   6,
391   {
392     { ShowMachineInfo, NULLMENU, 2, {
393       {"show","Get machine information"},
394       {"name","Machine's Name: "}
395     } },
396     { AddMachine, NULLMENU, 2, {
397       {"add","Add a new machine"},
398       {"name","Machine's Name: "},
399     } },
400     { UpdateMachine, NULLMENU, 2, {
401       {"update","Update machine information"},
402       {"name","Machine's Name: "},
403     } },
404     { DeleteMachine, NULLMENU, 2, {
405       {"delete","Delete this machine"},
406       {"name","Machine's Name: "}
407     } },
408     SUBMENU("mappings","Machine To Cluster Mappings Menu", &mappings_menu),
409     SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode)
410   }
411 };
412
413 /*
414  * List Menu
415  */
416
417 Menu list_menu = {
418     NULLFUNC,
419     NULLFUNC,
420     "List Menu",
421     9,
422     {
423         { ShowListInfo, NULLMENU, 2, {
424             {"show", "Display information about a list"},
425             {"list name", "Name of list: "}
426         } },
427         { NULLFUNC, &list_member_menu, 2, {
428             {"add", "Create new List"},
429             {"list name", "Name of list: "}
430         } },
431         { UpdateList, NULLMENU, 2, {
432             {"update", "Update characteristics of a list"},
433             {"list name", "Name of list: "}
434         } },
435         { DeleteList, NULLMENU, 2, {
436             {"delete", "Delete a List"},
437             {"list name", "Name of list: "}
438         } },
439         SIMPLEFUNC("query_remove",
440                    "Interactively remove an item from all lists",
441                    InterRemoveItemFromLists),
442         { NULLFUNC, &list_member_menu, 2, {
443             {"members", "Member Menu - Change/Show Members of a List."},
444             {"list name", "Name of list: "}
445         } },
446         SUBMENU("list_info", "List Info Menu",
447                 &list_info_menu),
448         SUBMENU("quotas","Quota Menu", &quota_menu),    
449 /*      SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode), */
450         SIMPLEFUNC("help", "Print Help", ListHelp)
451     } 
452 };
453
454 /*
455  * NFS Physical Menu
456  */
457
458 Menu nfsphys_menu = {
459   NULLFUNC,
460   NULLFUNC,
461   "NFS Physical Menu",
462   6,
463   {
464     { ShowNFSService, NULLMENU, 2, {
465       { "show", "Show an NFS server" },
466       { "machine", "Machine Name: "},
467     } },
468     { AddNFSService, NULLMENU, 2, {
469       { "add", "Add NFS server" },
470       { "machine", "Machine Name: "},
471     } },
472     { UpdateNFSService, NULLMENU, 2, {
473       { "update", "Update NFS server"},
474       { "machine", "Machine Name: "},
475     } },
476     { DeleteNFSService, NULLMENU, 2, {
477       { "delete", "Delete NFS server"},
478       {"machine", "Machine Name: "},
479     } },
480     SUBMENU("quotas","Quota Menu", &quota_menu),
481     SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode),
482 /*    SIMPLEFUNC("help", "Help", NFSHelp), */
483   }
484 };
485
486 Menu krbmap_menu = {
487     NULLFUNC,
488     NULLFUNC,
489     "User Kerberos Mapping Menu",
490     3,
491     {
492         { GetKrbmap, NULLMENU, 3, {
493             { "show", "Show Kerberos Mappings" },
494             { "user", "User login name: " },
495             { "principal", "Principal: " },
496         } },
497         { AddKrbmap, NULLMENU, 3, {
498             { "add", "Add Kerberos Mapping" },
499             { "user", "User login name: " },
500             { "principal", "Principal (this is case sensitive): " },
501         } },
502         { DeleteKrbmap, NULLMENU, 3, {
503             { "delete", "Delete Kerberos Mapping" },
504             { "user", "User login name: " },
505             { "principal", "Principal: " },
506         } },
507     }
508 };
509
510 /*
511  * User Menu
512  */
513
514 Menu user_menu = {
515   NULLFUNC,
516   NULLFUNC,
517   "User Menu",
518   11,
519   {
520     {ShowUserByLogin, NULLMENU, 2, {
521        {"login", "Show user information by login name"},
522        {"login name", "Desired login name: "}
523      } },
524     {ShowUserByName, NULLMENU, 3, {
525       {"name", "Show user information by name"},
526       {"first", "First name: "},
527       {"last", "Last name: "}
528     } },
529     {ShowUserByClass, NULLMENU, 2, {
530        {"class", "Show names of users in a given class"},
531        {"login name", "Desired class: "}
532      } },    
533     {UpdateUser, NULLMENU, 2, {
534       {"modify", "Change all user fields"},
535       {"login", "Login name: "}
536     } },
537     SIMPLEFUNC("adduser", "Add a new user to the database", 
538                AddNewUser),
539     SIMPLEFUNC("register", "Register a user", RegisterUser),
540     {DeactivateUser, NULLMENU, 2, {
541       {"deactivate", "Deactivate user"},
542       {"login", "Login name: "},
543     } },
544     {DeleteUser, NULLMENU, 2, {
545       {"expunge", "Expunge user"},
546       {"login", "Login name: "}
547     } },
548     SUBMENU("pobox", "Post Office Box Menu", &pobox_menu),
549     SUBMENU("quota", "Quota Menu", &quota_menu),
550     SUBMENU("krbmap", "User Kerberos Mappings", &krbmap_menu),
551   }
552 };
553
554 Menu dcm_menu = {
555     NULLFUNC,
556     NULLFUNC,
557     "DCM Menu",
558     6,
559     {
560         SIMPLEFUNC("enable", "Enable/disable DCM", EnableDcm),
561         SUBMENU("service", "DCM Service Menu", &service_menu),
562         SUBMENU("host", "DCM Host Menu", &host_menu),
563         SIMPLEFUNC("active", "Display entries currently being updated",
564                    InProgress),
565         SIMPLEFUNC("failed", "Display entries with errors to be reset",
566                    DcmFailed),
567         SIMPLEFUNC("dcm", "Invoke a DCM update now", Dcm),
568     }
569 };
570
571 /* 
572  * Printcap Printer Menu
573  */
574
575 Menu printer_menu = {
576   NULLFUNC, 
577   NULLFUNC, 
578   "Printer Menu",
579   4,
580   {
581     { GetPcap, NULLMENU, 2, {
582       {"get", "Get Printcap Entry Information"},
583       {"name", "Name of Printer: "}
584     } },
585     { AddPcap, NULLMENU, 2, {
586       {"add", "Add New Printcap Entry to Database"},
587       {"name", "name: "},
588     } },
589     { ChngPcap, NULLMENU, 2, {
590       {"change", "Update Printer Information"},
591       {"name", "name: "},
592     } },
593     { DeletePcap, NULLMENU, 2, {
594       {"delete", "Delete Printcap Entry"},
595       {"name", "Printer Name: "}
596     } }
597   }
598 };
599
600
601 /* 
602  * Palladium Printer Menu
603  */
604
605 Menu palladium_menu = {
606   NULLFUNC, 
607   NULLFUNC, 
608   "Printer Menu",
609   7,
610   {
611     { GetPalladium, NULLMENU, 2, {
612       {"get", "Get Palladium Server/Supervisor Information"},
613       {"name", "Name of Printer: "}
614     } },
615     { AddPalladium, NULLMENU, 2, {
616       {"add", "Add New Palladium Server/Supervisor to Database"},
617       {"name", "Supervisor/server name: "},
618     } },
619     { ChngPalladium, NULLMENU, 2, {
620       {"change", "Update Palladium Server/Supervisor Information"},
621       {"name", "name: "},
622     } },
623     { DeletePalladium, NULLMENU, 2, {
624       {"delete", "Delete Palladium Server/Supervisor Entry"},
625       {"name", "Printer Name: "}
626     } },
627     { ShowPalladiumAlias, NULLMENU, 3, {
628       {"getprinter", "Show Logical Printers"},
629       {"newname", "Printer name: "},
630       {"server", "Supervisor or Server name: "},
631     } },
632     { AddPalladiumAlias, NULLMENU, 3, {
633       {"addprinter", "Add Logical Printer"},
634       {"newname", "New printer: "},
635       {"server", "Supervisor or Server name: "},
636     } },
637     { DeletePalladiumAlias, NULLMENU, 3, {
638       {"delprinter", "Remove Logical Printer"},
639       {"newname", "Printer name: "},
640       {"server", "Supervisor or Server name: "},
641     } },
642   }
643 };
644
645
646
647 /*
648  * Zephyr Menu
649  */
650
651 Menu zephyr_menu = {
652     NULLFUNC,
653     NULLFUNC,
654     "Zephyr Menu",
655     5,
656     {
657         { GetZephyr, NULLMENU, 2, {
658             {"get", "Get Zephyr Class Information"},
659             {"name", "Name of class: "}
660         } },
661         { AddZephyr, NULLMENU, 2, {
662             {"add", "Add New Zephyr class restrictions"},
663             {"name", "Class name: "},
664         } },
665         { ChngZephyr, NULLMENU, 2, {
666             {"change", "Update Zephyr class restrictions"},
667             {"name", "Class name: "},
668         } },
669         { DeleteZephyr, NULLMENU, 2, {
670             {"delete", "Delete Zephyr class restriction"},
671             {"name", "Class Name: "}
672         } },
673         { NULLFUNC, &list_member_menu, 2, {
674             {"members", "Member Menu - Change/Show Members of a List."},
675             {"list name", "Name of list: "}
676         } },
677     }
678 };
679
680
681 /*
682  * Miscellaneous Menu
683  */
684
685 Menu misc_menu = {
686     NULLFUNC,
687     NULLFUNC,
688     "Miscellaneous Menu",
689     4,
690     {
691         SIMPLEFUNC("statistics", "Show database statistics", TableStats),
692         SIMPLEFUNC("clients", "Show active Moira clients", ShowClients),
693         { ShowValue, NULLMENU, 2, {
694             {"getval", "Show a database variable value"},
695             {"name", "variable name: "},
696         } },
697         { ShowAlias, NULLMENU, 3, {
698             {"getalias", "Show an alias relation"},
699             {"name", "Alias name: "},
700             {"type", "Alias type: "},
701         } },
702     }
703 };
704
705
706 /* ------------------------- Root Menu ------------------------- */
707
708 /* 
709  * Moira top menu
710  */
711
712 Menu moira_top_menu = {
713   NULLFUNC,
714   NULLFUNC,
715   "Moira Database Manipulation",
716   11,
717   {
718     SUBMENU("cluster","Cluster Menu",&cluster_menu),
719     SUBMENU("filesys","Filesystem Menu", &filesys_menu),
720     SUBMENU("list","Lists and Group Menu", &list_menu),
721     SUBMENU("machine","Machine Menu",&machine_menu),
722     SUBMENU("nfs","NFS Physical Menu", &nfsphys_menu),
723     SUBMENU("user","User Menu", &user_menu),
724     SUBMENU("printcap", "Printcap Printer Menu", &printer_menu),
725     SUBMENU("palladium", "Palladium Printer Menu", &palladium_menu),
726     SUBMENU("zephyr", "Zephyr ACLS Menu", &zephyr_menu),
727     SUBMENU("dcm", "DCM Menu", &dcm_menu),
728     SUBMENU("misc", "Miscellaneous Menu", &misc_menu)
729   }
730 };  
This page took 0.098513 seconds and 5 git commands to generate.