perf tools: Add per-pkg format file parsing
[deliverable/linux.git] / tools / perf / util / pmu.c
1 #include <linux/list.h>
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include <stdio.h>
5 #include <stdbool.h>
6 #include <stdarg.h>
7 #include <dirent.h>
8 #include <api/fs/fs.h>
9 #include <locale.h>
10 #include "util.h"
11 #include "pmu.h"
12 #include "parse-events.h"
13 #include "cpumap.h"
14
15 struct perf_pmu_format {
16 char *name;
17 int value;
18 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
19 struct list_head list;
20 };
21
22 #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
23
24 int perf_pmu_parse(struct list_head *list, char *name);
25 extern FILE *perf_pmu_in;
26
27 static LIST_HEAD(pmus);
28
29 /*
30 * Parse & process all the sysfs attributes located under
31 * the directory specified in 'dir' parameter.
32 */
33 int perf_pmu__format_parse(char *dir, struct list_head *head)
34 {
35 struct dirent *evt_ent;
36 DIR *format_dir;
37 int ret = 0;
38
39 format_dir = opendir(dir);
40 if (!format_dir)
41 return -EINVAL;
42
43 while (!ret && (evt_ent = readdir(format_dir))) {
44 char path[PATH_MAX];
45 char *name = evt_ent->d_name;
46 FILE *file;
47
48 if (!strcmp(name, ".") || !strcmp(name, ".."))
49 continue;
50
51 snprintf(path, PATH_MAX, "%s/%s", dir, name);
52
53 ret = -EINVAL;
54 file = fopen(path, "r");
55 if (!file)
56 break;
57
58 perf_pmu_in = file;
59 ret = perf_pmu_parse(head, name);
60 fclose(file);
61 }
62
63 closedir(format_dir);
64 return ret;
65 }
66
67 /*
68 * Reading/parsing the default pmu format definition, which should be
69 * located at:
70 * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
71 */
72 static int pmu_format(const char *name, struct list_head *format)
73 {
74 struct stat st;
75 char path[PATH_MAX];
76 const char *sysfs = sysfs__mountpoint();
77
78 if (!sysfs)
79 return -1;
80
81 snprintf(path, PATH_MAX,
82 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
83
84 if (stat(path, &st) < 0)
85 return 0; /* no error if format does not exist */
86
87 if (perf_pmu__format_parse(path, format))
88 return -1;
89
90 return 0;
91 }
92
93 static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
94 {
95 struct stat st;
96 ssize_t sret;
97 char scale[128];
98 int fd, ret = -1;
99 char path[PATH_MAX];
100 const char *lc;
101
102 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
103
104 fd = open(path, O_RDONLY);
105 if (fd == -1)
106 return -1;
107
108 if (fstat(fd, &st) < 0)
109 goto error;
110
111 sret = read(fd, scale, sizeof(scale)-1);
112 if (sret < 0)
113 goto error;
114
115 scale[sret] = '\0';
116 /*
117 * save current locale
118 */
119 lc = setlocale(LC_NUMERIC, NULL);
120
121 /*
122 * force to C locale to ensure kernel
123 * scale string is converted correctly.
124 * kernel uses default C locale.
125 */
126 setlocale(LC_NUMERIC, "C");
127
128 alias->scale = strtod(scale, NULL);
129
130 /* restore locale */
131 setlocale(LC_NUMERIC, lc);
132
133 ret = 0;
134 error:
135 close(fd);
136 return ret;
137 }
138
139 static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
140 {
141 char path[PATH_MAX];
142 ssize_t sret;
143 int fd;
144
145 snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
146
147 fd = open(path, O_RDONLY);
148 if (fd == -1)
149 return -1;
150
151 sret = read(fd, alias->unit, UNIT_MAX_LEN);
152 if (sret < 0)
153 goto error;
154
155 close(fd);
156
157 alias->unit[sret] = '\0';
158
159 return 0;
160 error:
161 close(fd);
162 alias->unit[0] = '\0';
163 return -1;
164 }
165
166 static int
167 perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
168 {
169 char path[PATH_MAX];
170 int fd;
171
172 snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
173
174 fd = open(path, O_RDONLY);
175 if (fd == -1)
176 return -1;
177
178 close(fd);
179
180 alias->per_pkg = true;
181 return 0;
182 }
183
184 static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
185 {
186 struct perf_pmu_alias *alias;
187 char buf[256];
188 int ret;
189
190 ret = fread(buf, 1, sizeof(buf), file);
191 if (ret == 0)
192 return -EINVAL;
193 buf[ret] = 0;
194
195 alias = malloc(sizeof(*alias));
196 if (!alias)
197 return -ENOMEM;
198
199 INIT_LIST_HEAD(&alias->terms);
200 alias->scale = 1.0;
201 alias->unit[0] = '\0';
202 alias->per_pkg = false;
203
204 ret = parse_events_terms(&alias->terms, buf);
205 if (ret) {
206 free(alias);
207 return ret;
208 }
209
210 alias->name = strdup(name);
211 /*
212 * load unit name and scale if available
213 */
214 perf_pmu__parse_unit(alias, dir, name);
215 perf_pmu__parse_scale(alias, dir, name);
216 perf_pmu__parse_per_pkg(alias, dir, name);
217
218 list_add_tail(&alias->list, list);
219
220 return 0;
221 }
222
223 static inline bool pmu_alias_info_file(char *name)
224 {
225 size_t len;
226
227 len = strlen(name);
228 if (len > 5 && !strcmp(name + len - 5, ".unit"))
229 return true;
230 if (len > 6 && !strcmp(name + len - 6, ".scale"))
231 return true;
232 if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
233 return true;
234
235 return false;
236 }
237
238 /*
239 * Process all the sysfs attributes located under the directory
240 * specified in 'dir' parameter.
241 */
242 static int pmu_aliases_parse(char *dir, struct list_head *head)
243 {
244 struct dirent *evt_ent;
245 DIR *event_dir;
246 int ret = 0;
247
248 event_dir = opendir(dir);
249 if (!event_dir)
250 return -EINVAL;
251
252 while (!ret && (evt_ent = readdir(event_dir))) {
253 char path[PATH_MAX];
254 char *name = evt_ent->d_name;
255 FILE *file;
256
257 if (!strcmp(name, ".") || !strcmp(name, ".."))
258 continue;
259
260 /*
261 * skip info files parsed in perf_pmu__new_alias()
262 */
263 if (pmu_alias_info_file(name))
264 continue;
265
266 snprintf(path, PATH_MAX, "%s/%s", dir, name);
267
268 ret = -EINVAL;
269 file = fopen(path, "r");
270 if (!file)
271 break;
272
273 ret = perf_pmu__new_alias(head, dir, name, file);
274 fclose(file);
275 }
276
277 closedir(event_dir);
278 return ret;
279 }
280
281 /*
282 * Reading the pmu event aliases definition, which should be located at:
283 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
284 */
285 static int pmu_aliases(const char *name, struct list_head *head)
286 {
287 struct stat st;
288 char path[PATH_MAX];
289 const char *sysfs = sysfs__mountpoint();
290
291 if (!sysfs)
292 return -1;
293
294 snprintf(path, PATH_MAX,
295 "%s/bus/event_source/devices/%s/events", sysfs, name);
296
297 if (stat(path, &st) < 0)
298 return 0; /* no error if 'events' does not exist */
299
300 if (pmu_aliases_parse(path, head))
301 return -1;
302
303 return 0;
304 }
305
306 static int pmu_alias_terms(struct perf_pmu_alias *alias,
307 struct list_head *terms)
308 {
309 struct parse_events_term *term, *cloned;
310 LIST_HEAD(list);
311 int ret;
312
313 list_for_each_entry(term, &alias->terms, list) {
314 ret = parse_events_term__clone(&cloned, term);
315 if (ret) {
316 parse_events__free_terms(&list);
317 return ret;
318 }
319 list_add_tail(&cloned->list, &list);
320 }
321 list_splice(&list, terms);
322 return 0;
323 }
324
325 /*
326 * Reading/parsing the default pmu type value, which should be
327 * located at:
328 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
329 */
330 static int pmu_type(const char *name, __u32 *type)
331 {
332 struct stat st;
333 char path[PATH_MAX];
334 FILE *file;
335 int ret = 0;
336 const char *sysfs = sysfs__mountpoint();
337
338 if (!sysfs)
339 return -1;
340
341 snprintf(path, PATH_MAX,
342 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
343
344 if (stat(path, &st) < 0)
345 return -1;
346
347 file = fopen(path, "r");
348 if (!file)
349 return -EINVAL;
350
351 if (1 != fscanf(file, "%u", type))
352 ret = -1;
353
354 fclose(file);
355 return ret;
356 }
357
358 /* Add all pmus in sysfs to pmu list: */
359 static void pmu_read_sysfs(void)
360 {
361 char path[PATH_MAX];
362 DIR *dir;
363 struct dirent *dent;
364 const char *sysfs = sysfs__mountpoint();
365
366 if (!sysfs)
367 return;
368
369 snprintf(path, PATH_MAX,
370 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
371
372 dir = opendir(path);
373 if (!dir)
374 return;
375
376 while ((dent = readdir(dir))) {
377 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
378 continue;
379 /* add to static LIST_HEAD(pmus): */
380 perf_pmu__find(dent->d_name);
381 }
382
383 closedir(dir);
384 }
385
386 static struct cpu_map *pmu_cpumask(const char *name)
387 {
388 struct stat st;
389 char path[PATH_MAX];
390 FILE *file;
391 struct cpu_map *cpus;
392 const char *sysfs = sysfs__mountpoint();
393
394 if (!sysfs)
395 return NULL;
396
397 snprintf(path, PATH_MAX,
398 "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
399
400 if (stat(path, &st) < 0)
401 return NULL;
402
403 file = fopen(path, "r");
404 if (!file)
405 return NULL;
406
407 cpus = cpu_map__read(file);
408 fclose(file);
409 return cpus;
410 }
411
412 struct perf_event_attr *__attribute__((weak))
413 perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
414 {
415 return NULL;
416 }
417
418 static struct perf_pmu *pmu_lookup(const char *name)
419 {
420 struct perf_pmu *pmu;
421 LIST_HEAD(format);
422 LIST_HEAD(aliases);
423 __u32 type;
424
425 /*
426 * The pmu data we store & need consists of the pmu
427 * type value and format definitions. Load both right
428 * now.
429 */
430 if (pmu_format(name, &format))
431 return NULL;
432
433 if (pmu_aliases(name, &aliases))
434 return NULL;
435
436 if (pmu_type(name, &type))
437 return NULL;
438
439 pmu = zalloc(sizeof(*pmu));
440 if (!pmu)
441 return NULL;
442
443 pmu->cpus = pmu_cpumask(name);
444
445 INIT_LIST_HEAD(&pmu->format);
446 INIT_LIST_HEAD(&pmu->aliases);
447 list_splice(&format, &pmu->format);
448 list_splice(&aliases, &pmu->aliases);
449 pmu->name = strdup(name);
450 pmu->type = type;
451 list_add_tail(&pmu->list, &pmus);
452
453 pmu->default_config = perf_pmu__get_default_config(pmu);
454
455 return pmu;
456 }
457
458 static struct perf_pmu *pmu_find(const char *name)
459 {
460 struct perf_pmu *pmu;
461
462 list_for_each_entry(pmu, &pmus, list)
463 if (!strcmp(pmu->name, name))
464 return pmu;
465
466 return NULL;
467 }
468
469 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
470 {
471 /*
472 * pmu iterator: If pmu is NULL, we start at the begin,
473 * otherwise return the next pmu. Returns NULL on end.
474 */
475 if (!pmu) {
476 pmu_read_sysfs();
477 pmu = list_prepare_entry(pmu, &pmus, list);
478 }
479 list_for_each_entry_continue(pmu, &pmus, list)
480 return pmu;
481 return NULL;
482 }
483
484 struct perf_pmu *perf_pmu__find(const char *name)
485 {
486 struct perf_pmu *pmu;
487
488 /*
489 * Once PMU is loaded it stays in the list,
490 * so we keep us from multiple reading/parsing
491 * the pmu format definitions.
492 */
493 pmu = pmu_find(name);
494 if (pmu)
495 return pmu;
496
497 return pmu_lookup(name);
498 }
499
500 static struct perf_pmu_format *
501 pmu_find_format(struct list_head *formats, char *name)
502 {
503 struct perf_pmu_format *format;
504
505 list_for_each_entry(format, formats, list)
506 if (!strcmp(format->name, name))
507 return format;
508
509 return NULL;
510 }
511
512 /*
513 * Sets value based on the format definition (format parameter)
514 * and unformated value (value parameter).
515 */
516 static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
517 bool zero)
518 {
519 unsigned long fbit, vbit;
520
521 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
522
523 if (!test_bit(fbit, format))
524 continue;
525
526 if (value & (1llu << vbit++))
527 *v |= (1llu << fbit);
528 else if (zero)
529 *v &= ~(1llu << fbit);
530 }
531 }
532
533 /*
534 * Setup one of config[12] attr members based on the
535 * user input data - term parameter.
536 */
537 static int pmu_config_term(struct list_head *formats,
538 struct perf_event_attr *attr,
539 struct parse_events_term *term,
540 bool zero)
541 {
542 struct perf_pmu_format *format;
543 __u64 *vp;
544
545 /*
546 * Support only for hardcoded and numnerial terms.
547 * Hardcoded terms should be already in, so nothing
548 * to be done for them.
549 */
550 if (parse_events__is_hardcoded_term(term))
551 return 0;
552
553 if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
554 return -EINVAL;
555
556 format = pmu_find_format(formats, term->config);
557 if (!format)
558 return -EINVAL;
559
560 switch (format->value) {
561 case PERF_PMU_FORMAT_VALUE_CONFIG:
562 vp = &attr->config;
563 break;
564 case PERF_PMU_FORMAT_VALUE_CONFIG1:
565 vp = &attr->config1;
566 break;
567 case PERF_PMU_FORMAT_VALUE_CONFIG2:
568 vp = &attr->config2;
569 break;
570 default:
571 return -EINVAL;
572 }
573
574 /*
575 * XXX If we ever decide to go with string values for
576 * non-hardcoded terms, here's the place to translate
577 * them into value.
578 */
579 pmu_format_value(format->bits, term->val.num, vp, zero);
580 return 0;
581 }
582
583 int perf_pmu__config_terms(struct list_head *formats,
584 struct perf_event_attr *attr,
585 struct list_head *head_terms,
586 bool zero)
587 {
588 struct parse_events_term *term;
589
590 list_for_each_entry(term, head_terms, list)
591 if (pmu_config_term(formats, attr, term, zero))
592 return -EINVAL;
593
594 return 0;
595 }
596
597 /*
598 * Configures event's 'attr' parameter based on the:
599 * 1) users input - specified in terms parameter
600 * 2) pmu format definitions - specified by pmu parameter
601 */
602 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
603 struct list_head *head_terms)
604 {
605 bool zero = !!pmu->default_config;
606
607 attr->type = pmu->type;
608 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
609 }
610
611 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
612 struct parse_events_term *term)
613 {
614 struct perf_pmu_alias *alias;
615 char *name;
616
617 if (parse_events__is_hardcoded_term(term))
618 return NULL;
619
620 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
621 if (term->val.num != 1)
622 return NULL;
623 if (pmu_find_format(&pmu->format, term->config))
624 return NULL;
625 name = term->config;
626 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
627 if (strcasecmp(term->config, "event"))
628 return NULL;
629 name = term->val.str;
630 } else {
631 return NULL;
632 }
633
634 list_for_each_entry(alias, &pmu->aliases, list) {
635 if (!strcasecmp(alias->name, name))
636 return alias;
637 }
638 return NULL;
639 }
640
641
642 static int check_unit_scale(struct perf_pmu_alias *alias,
643 const char **unit, double *scale)
644 {
645 /*
646 * Only one term in event definition can
647 * define unit and scale, fail if there's
648 * more than one.
649 */
650 if ((*unit && alias->unit) ||
651 (*scale && alias->scale))
652 return -EINVAL;
653
654 if (alias->unit)
655 *unit = alias->unit;
656
657 if (alias->scale)
658 *scale = alias->scale;
659
660 return 0;
661 }
662
663 /*
664 * Find alias in the terms list and replace it with the terms
665 * defined for the alias
666 */
667 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
668 struct perf_pmu_info *info)
669 {
670 struct parse_events_term *term, *h;
671 struct perf_pmu_alias *alias;
672 int ret;
673
674 info->per_pkg = false;
675
676 /*
677 * Mark unit and scale as not set
678 * (different from default values, see below)
679 */
680 info->unit = NULL;
681 info->scale = 0.0;
682
683 list_for_each_entry_safe(term, h, head_terms, list) {
684 alias = pmu_find_alias(pmu, term);
685 if (!alias)
686 continue;
687 ret = pmu_alias_terms(alias, &term->list);
688 if (ret)
689 return ret;
690
691 ret = check_unit_scale(alias, &info->unit, &info->scale);
692 if (ret)
693 return ret;
694
695 if (alias->per_pkg)
696 info->per_pkg = true;
697
698 list_del(&term->list);
699 free(term);
700 }
701
702 /*
703 * if no unit or scale foundin aliases, then
704 * set defaults as for evsel
705 * unit cannot left to NULL
706 */
707 if (info->unit == NULL)
708 info->unit = "";
709
710 if (info->scale == 0.0)
711 info->scale = 1.0;
712
713 return 0;
714 }
715
716 int perf_pmu__new_format(struct list_head *list, char *name,
717 int config, unsigned long *bits)
718 {
719 struct perf_pmu_format *format;
720
721 format = zalloc(sizeof(*format));
722 if (!format)
723 return -ENOMEM;
724
725 format->name = strdup(name);
726 format->value = config;
727 memcpy(format->bits, bits, sizeof(format->bits));
728
729 list_add_tail(&format->list, list);
730 return 0;
731 }
732
733 void perf_pmu__set_format(unsigned long *bits, long from, long to)
734 {
735 long b;
736
737 if (!to)
738 to = from;
739
740 memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
741 for (b = from; b <= to; b++)
742 set_bit(b, bits);
743 }
744
745 static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
746 struct perf_pmu_alias *alias)
747 {
748 snprintf(buf, len, "%s/%s/", pmu->name, alias->name);
749 return buf;
750 }
751
752 static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
753 struct perf_pmu_alias *alias)
754 {
755 snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
756 return buf;
757 }
758
759 static int cmp_string(const void *a, const void *b)
760 {
761 const char * const *as = a;
762 const char * const *bs = b;
763 return strcmp(*as, *bs);
764 }
765
766 void print_pmu_events(const char *event_glob, bool name_only)
767 {
768 struct perf_pmu *pmu;
769 struct perf_pmu_alias *alias;
770 char buf[1024];
771 int printed = 0;
772 int len, j;
773 char **aliases;
774
775 pmu = NULL;
776 len = 0;
777 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
778 list_for_each_entry(alias, &pmu->aliases, list)
779 len++;
780 if (pmu->selectable)
781 len++;
782 }
783 aliases = zalloc(sizeof(char *) * len);
784 if (!aliases)
785 goto out_enomem;
786 pmu = NULL;
787 j = 0;
788 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
789 list_for_each_entry(alias, &pmu->aliases, list) {
790 char *name = format_alias(buf, sizeof(buf), pmu, alias);
791 bool is_cpu = !strcmp(pmu->name, "cpu");
792
793 if (event_glob != NULL &&
794 !(strglobmatch(name, event_glob) ||
795 (!is_cpu && strglobmatch(alias->name,
796 event_glob))))
797 continue;
798
799 if (is_cpu && !name_only)
800 name = format_alias_or(buf, sizeof(buf), pmu, alias);
801
802 aliases[j] = strdup(name);
803 if (aliases[j] == NULL)
804 goto out_enomem;
805 j++;
806 }
807 if (pmu->selectable) {
808 char *s;
809 if (asprintf(&s, "%s//", pmu->name) < 0)
810 goto out_enomem;
811 aliases[j] = s;
812 j++;
813 }
814 }
815 len = j;
816 qsort(aliases, len, sizeof(char *), cmp_string);
817 for (j = 0; j < len; j++) {
818 if (name_only) {
819 printf("%s ", aliases[j]);
820 continue;
821 }
822 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
823 printed++;
824 }
825 if (printed)
826 printf("\n");
827 out_free:
828 for (j = 0; j < len; j++)
829 zfree(&aliases[j]);
830 zfree(&aliases);
831 return;
832
833 out_enomem:
834 printf("FATAL: not enough memory to print PMU events\n");
835 if (aliases)
836 goto out_free;
837 }
838
839 bool pmu_have_event(const char *pname, const char *name)
840 {
841 struct perf_pmu *pmu;
842 struct perf_pmu_alias *alias;
843
844 pmu = NULL;
845 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
846 if (strcmp(pname, pmu->name))
847 continue;
848 list_for_each_entry(alias, &pmu->aliases, list)
849 if (!strcmp(alias->name, name))
850 return true;
851 }
852 return false;
853 }
854
855 static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
856 {
857 struct stat st;
858 char path[PATH_MAX];
859 const char *sysfs;
860
861 sysfs = sysfs__mountpoint();
862 if (!sysfs)
863 return NULL;
864
865 snprintf(path, PATH_MAX,
866 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
867
868 if (stat(path, &st) < 0)
869 return NULL;
870
871 return fopen(path, "r");
872 }
873
874 int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
875 ...)
876 {
877 va_list args;
878 FILE *file;
879 int ret = EOF;
880
881 va_start(args, fmt);
882 file = perf_pmu__open_file(pmu, name);
883 if (file) {
884 ret = vfscanf(file, fmt, args);
885 fclose(file);
886 }
887 va_end(args);
888 return ret;
889 }
This page took 0.048714 seconds and 5 git commands to generate.