Hello community, here is the log from the commit of package hwinfo checked in at Fri Aug 24 01:11:14 CEST 2007. -------- --- hwinfo/hwinfo.changes 2007-08-20 17:45:31.000000000 +0200 +++ /mounts/work_src_done/STABLE/hwinfo/hwinfo.changes 2007-08-22 17:16:32.000000000 +0200 @@ -1,0 +2,7 @@ +Wed Aug 22 17:16:27 CEST 2007 - snwint@suse.de + +- prepare for upcoming sysfs change (#299685) +- updated X11 data +- monitor detection: handle >1 detailed timing info block + +------------------------------------------------------------------- Old: ---- hwinfo-13.45.tar.bz2 New: ---- hwinfo-13.46.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ hwinfo.spec ++++++ --- /var/tmp/diff_new_pack.l18556/_old 2007-08-24 01:09:43.000000000 +0200 +++ /var/tmp/diff_new_pack.l18556/_new 2007-08-24 01:09:43.000000000 +0200 @@ -1,5 +1,5 @@ # -# spec file for package hwinfo (Version 13.45) +# spec file for package hwinfo (Version 13.46) # # Copyright (c) 2007 SUSE LINUX Products GmbH, Nuernberg, Germany. # This file and all modifications and additions to the pristine @@ -20,9 +20,9 @@ PreReq: /sbin/ldconfig %insserv_prereq %fillup_prereq Autoreqprov: on Summary: Hardware Library -Version: 13.45 +Version: 13.46 Release: 1 -Source: hwinfo-13.45.tar.bz2 +Source: hwinfo-13.46.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-build %description @@ -89,6 +89,10 @@ %doc doc/libhd/html %changelog +* Wed Aug 22 2007 - snwint@suse.de +- prepare for upcoming sysfs change (#299685) +- updated X11 data +- monitor detection: handle >1 detailed timing info block * Mon Aug 20 2007 - snwint@suse.de - deprecate sk98in (#298724) - fix ppc buffer overrun (#301752) ++++++ hwinfo-13.45.tar.bz2 -> hwinfo-13.46.tar.bz2 ++++++ diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/Changelog new/hwinfo-13.46/Changelog --- old/hwinfo-13.45/Changelog 2007-08-20 17:45:19.000000000 +0200 +++ new/hwinfo-13.46/Changelog 2007-08-22 16:48:44.000000000 +0200 @@ -1,3 +1,8 @@ +22/8/2007: v13.46 + - prepare for upcoming sysfs change (#299685) + - updated X11 data + - monitor detection: handle >1 detailed timing info block + 20/8/2007: v13.45 - deprecate sk98in (#298724) - fix ppc buffer overrun (#301752) diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/src/hd/block.c new/hwinfo-13.46/src/hd/block.c --- old/hwinfo-13.45/src/hd/block.c 2007-03-27 12:42:07.000000000 +0200 +++ new/hwinfo-13.46/src/hd/block.c 2007-08-21 11:32:36.000000000 +0200 @@ -97,6 +97,7 @@ char *sf_cdev = NULL, *sf_dev = NULL, *sf_dev_ide; char *sf_drv_name, *sf_drv, *bus_id, *bus_name, *ide_bus_id; str_list_t *sf_bus, *sf_bus_e; + char *sf_block_dir; sf_bus = reverse_str_list(read_dir("/sys/bus/ide/devices", 'l')); @@ -112,7 +113,18 @@ } } - sf_class = reverse_str_list(read_dir("/sys/block", 'd')); + sf_block_dir = "/sys/subsystem/block"; + sf_class = reverse_str_list(read_dir(sf_block_dir, 'l')); + + if (!sf_class) { + sf_block_dir = "/sys/class/block"; + sf_class = reverse_str_list(read_dir(sf_block_dir, 'l')); + } + + if (!sf_class) { + sf_block_dir = "/sys/block"; + sf_class = reverse_str_list(read_dir(sf_block_dir, 'd')); + } if(!sf_class) { ADD2LOG("sysfs: no such class: block\n"); @@ -120,8 +132,7 @@ } for(sf_class_e = sf_class; sf_class_e; sf_class_e = sf_class_e->next) { - str_printf(&sf_cdev, 0, "/sys/block/%s", sf_class_e->str); - + str_printf(&sf_cdev, 0, "%s/%s", sf_block_dir, sf_class_e->str); ADD2LOG( " block: name = %s, path = %s\n", sf_class_e->str, diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/src/hd/hd.c new/hwinfo-13.46/src/hd/hd.c --- old/hwinfo-13.45/src/hd/hd.c 2007-07-16 10:40:51.000000000 +0200 +++ new/hwinfo-13.46/src/hd/hd.c 2007-08-22 16:34:38.000000000 +0200 @@ -1226,13 +1226,21 @@ case hd_detail_monitor: { - monitor_info_t *m = d->monitor.data; + monitor_info_t *m; + hd_detail_monitor_t *mdetail, *next; - free_mem(m->vendor); - free_mem(m->name); - free_mem(m->serial); + for(mdetail = &d->monitor; mdetail; mdetail = next) { + next = mdetail->next; + m = mdetail->data; - free_mem(m); + free_mem(m->vendor); + free_mem(m->name); + free_mem(m->serial); + + free_mem(m); + + if(mdetail != &d->monitor) free_mem(mdetail); + } } break; @@ -1259,9 +1267,9 @@ /* is freed with hd_data->dev_tree */ break; - case hd_detail_ccw: - free_mem(d->ccw.data); - break; + case hd_detail_ccw: + free_mem(d->ccw.data); + break; } free_mem(d); diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/src/hd/hd.h new/hwinfo-13.46/src/hd/hd.h --- old/hwinfo-13.45/src/hd/hd.h 2007-08-20 17:36:33.000000000 +0200 +++ new/hwinfo-13.46/src/hd/hd.h 2007-08-22 16:11:42.000000000 +0200 @@ -2074,9 +2074,10 @@ prom_info_t *data; } hd_detail_prom_t; -typedef struct { +typedef struct hd_detail_monitor_s { enum hd_detail_type type; monitor_info_t *data; + struct hd_detail_monitor_s *next; } hd_detail_monitor_t; typedef struct { diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/src/hd/hdp.c new/hwinfo-13.46/src/hd/hdp.c --- old/hwinfo-13.45/src/hd/hdp.c 2007-03-16 14:32:19.000000000 +0100 +++ new/hwinfo-13.46/src/hd/hdp.c 2007-08-22 16:27:16.000000000 +0200 @@ -372,6 +372,7 @@ str_list_t *sl, *sl1, *sl2; isdn_parm_t *ip; monitor_info_t *mi; + hd_detail_monitor_t *mdetail; static char *geo_type_str[] = { "Physical", "Logical", "BIOS EDD", "BIOS Legacy" }; if(h->model) dump_line("Model: \"%s\"\n", h->model); @@ -802,27 +803,31 @@ h->detail->type == hd_detail_monitor && (mi = h->detail->monitor.data) ) { - if(mi->htotal && mi->vtotal) { - dump_line_str("Detailed Timings:\n"); - dump_line(" Resolution: %ux%u\n", mi->width, mi->height); - dump_line( - " Horizontal: %4u %4u %4u %4u (+%u +%u +%u) %chsync\n", - mi->hdisp, mi->hsyncstart, mi->hsyncend, mi->htotal, - mi->hsyncstart - mi->hdisp, mi->hsyncend - mi->hdisp, mi->htotal - mi->hdisp, - mi->hflag - ); - dump_line( - " Vertical: %4u %4u %4u %4u (+%u +%u +%u) %cvsync\n", - mi->vdisp, mi->vsyncstart, mi->vsyncend, mi->vtotal, - mi->vsyncstart - mi->vdisp, mi->vsyncend - mi->vdisp, mi->vtotal - mi->vdisp, - mi->vflag - ); - dump_line( - " Frequencies: %.2f MHz, %.2f kHz, %.2f Hz\n", - (double) mi->clock / 1000, - (double) mi->clock / mi->htotal, - (double) mi->clock / mi->htotal / mi->vtotal * 1000 - ); + for(i = 0, mdetail = &h->detail->monitor; mdetail; i++, mdetail = mdetail->next) { + mi = mdetail->data; + + if(mi->htotal && mi->vtotal) { + dump_line("Detailed Timings #%d:\n", i); + dump_line(" Resolution: %ux%u\n", mi->width, mi->height); + dump_line( + " Horizontal: %4u %4u %4u %4u (+%u +%u +%u) %chsync\n", + mi->hdisp, mi->hsyncstart, mi->hsyncend, mi->htotal, + mi->hsyncstart - mi->hdisp, mi->hsyncend - mi->hdisp, mi->htotal - mi->hdisp, + mi->hflag + ); + dump_line( + " Vertical: %4u %4u %4u %4u (+%u +%u +%u) %cvsync\n", + mi->vdisp, mi->vsyncstart, mi->vsyncend, mi->vtotal, + mi->vsyncstart - mi->vdisp, mi->vsyncend - mi->vdisp, mi->vtotal - mi->vdisp, + mi->vflag + ); + dump_line( + " Frequencies: %.2f MHz, %.2f kHz, %.2f Hz\n", + (double) mi->clock / 1000, + (double) mi->clock / mi->htotal, + (double) mi->clock / mi->htotal / mi->vtotal * 1000 + ); + } } } diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/src/hd/monitor.c new/hwinfo-13.46/src/hd/monitor.c --- old/hwinfo-13.45/src/hd/monitor.c 2006-10-20 13:50:49.000000000 +0200 +++ new/hwinfo-13.46/src/hd/monitor.c 2007-08-22 16:46:05.000000000 +0200 @@ -32,6 +32,7 @@ static void add_monitor(hd_data_t *hd_data, devtree_t *dt); static int chk_edid_info(hd_data_t *hd_data, unsigned char *edid); static void add_lcd_info(hd_data_t *hd_data, hd_t *hd, bios_info_t *bt); +static int mi_cmp(monitor_info_t **mi0, monitor_info_t **mi1); static void add_edid_info(hd_data_t *hd_data, hd_t *hd, unsigned char *edid); static void add_monitor_res(hd_t *hd, unsigned x, unsigned y, unsigned hz, unsigned il); static void fix_edid_info(hd_data_t *hd_data, unsigned char *edid); @@ -288,20 +289,28 @@ } +int mi_cmp(monitor_info_t **mi0, monitor_info_t **mi1) +{ + return (*mi0)->hdisp * (*mi0)->vdisp - (*mi1)->hdisp * (*mi1)->vdisp; +} + + void add_edid_info(hd_data_t *hd_data, hd_t *hd, unsigned char *edid) { hd_res_t *res; - monitor_info_t *mi = NULL; + hd_detail_monitor_t *mdetail; + monitor_info_t *mi_list[4], *mi; + unsigned mi_cnt = 0; int i; unsigned u, u1, u2, tag; char *s; - unsigned width_mm = 0, height_mm = 0; + unsigned width_mm = 0, height_mm = 0, manu_year = 0; + unsigned min_vsync = 0, max_vsync = 0, min_hsync = 0, max_hsync = 0; unsigned hblank, hsync_ofs, hsync, vblank, vsync_ofs, vsync; + char *vendor = NULL, *serial = NULL, *name = NULL; fix_edid_info(hd_data, edid); - mi = new_mem(sizeof *mi); - if(edid[0x14] & 0x80) { /* digital signal -> assume lcd */ hd->sub_class.id = 2; @@ -316,8 +325,8 @@ } if(edid[0x15] > 0 && edid[0x16] > 0) { - mi->width_mm = width_mm = edid[0x15] * 10; - mi->height_mm = height_mm = edid[0x16] * 10; + width_mm = edid[0x15] * 10; + height_mm = edid[0x16] * 10; } u = edid[0x23]; @@ -352,10 +361,11 @@ if(u) add_monitor_res(hd, u1, u, (u2 & 0x3f) + 60, 0); } - mi->manu_year = 1990 + edid[0x11]; + manu_year = 1990 + edid[0x11]; ADD2LOG(" detailed timings:\n"); + /* max. 4 mi_list[] entries */ for(i = 0x36; i < 0x36 + 4 * 0x12; i += 0x12) { tag = (edid[i] << 24) + (edid[i + 1] << 16) + (edid[i + 2] << 8) + edid[i + 3]; @@ -367,7 +377,7 @@ case 0xfc: if(edid[i + 5]) { /* name entry is splitted some times */ - str_printf(&mi->name, -1, "%s%s", mi->name ? " " : "", canon_str(edid + i + 5, 0xd)); + str_printf(&name, -1, "%s%s", name ? " " : "", canon_str(edid + i + 5, 0xd)); } break; @@ -376,30 +386,30 @@ u1 = edid[i + 5]; u2 = edid[i + 6]; if(u1 > u2 || !u1) u = 1; - mi->min_vsync = u1; - mi->max_vsync = u2; + min_vsync = u1; + max_vsync = u2; u1 = edid[i + 7]; u2 = edid[i + 8]; if(u1 > u2 || !u1) u = 1; - mi->min_hsync = u1; - mi->max_hsync = u2; + min_hsync = u1; + max_hsync = u2; if(u) { - mi->min_vsync = mi->max_vsync = mi->min_hsync = mi->max_hsync = 0; + min_vsync = max_vsync = min_hsync = max_hsync = 0; ADD2LOG(" ddc oops: invalid freq data\n"); } break; case 0xfe: - if(!mi->vendor && edid[i + 5]) { - mi->vendor = canon_str(edid + i + 5, 0xd); - for(s = mi->vendor; *s; s++) if(*s < ' ') *s = ' '; + if(!vendor && edid[i + 5]) { + vendor = canon_str(edid + i + 5, 0xd); + for(s = vendor; *s; s++) if(*s < ' ') *s = ' '; } break; case 0xff: - if(!mi->serial && edid[i + 5]) { - mi->serial = canon_str(edid + i + 5, 0xd); - for(s = mi->serial; *s; s++) if(*s < ' ') *s = ' '; + if(!serial && edid[i + 5]) { + serial = canon_str(edid + i + 5, 0xd); + for(s = serial; *s; s++) if(*s < ' ') *s = ' '; } break; @@ -408,6 +418,24 @@ ADD2LOG(" unknown tag 0x%02x\n", tag); } else { + /* check for duplicates */ + + for(u1 = 1, u = 0x36; u < i; u += 0x12) { + u1 = memcmp(edid + u, edid + i, 0x12); + if(!u1) break; + } + + if(!u1) { + ADD2LOG(" duplicate of #%d - skipped\n", (u - 0x36)/0x12); + break; + } + + mi_list[mi_cnt++] = mi = new_mem(sizeof *mi); + + mi->width_mm = width_mm; + mi->height_mm = height_mm; + mi->manu_year = manu_year; + u = (edid[i + 0] + (edid[i + 1] << 8)) * 10; /* pixel clock in kHz */ if(!u) break; mi->clock = u; @@ -476,56 +504,80 @@ } } - if(mi) { - hd->detail = new_mem(sizeof *hd->detail); - hd->detail->type = hd_detail_monitor; - hd->detail->monitor.data = mi; - - hd->serial = new_str(mi->serial); - hd->vendor.name = new_str(mi->vendor); - hd->device.name = new_str(mi->name); - - if(mi->width && mi->height) { - for(res = hd->res; res; res = res->next) { - if( - res->any.type == res_monitor && - res->monitor.width == mi->width && - res->monitor.height == mi->height - ) break; - } - /* actually we could calculate the vsync value */ - if(!res) add_monitor_res(hd, mi->width, mi->height, 60, 0); - - /* do some sanity checks on display size, see bugs 155096, 186096, 213630 */ - if(mi->width_mm && mi->height_mm) { - u = (mi->width_mm * mi->height * 16) / (mi->height_mm * mi->width); - u1 = width_mm ? (width_mm * 16) / mi->width_mm : 16; - u2 = height_mm ? (height_mm * 16) / mi->height_mm : 16; - if( - u <= 8 || u >= 32 || /* allow 1:2 distortion */ - u1 <= 8 || u1 >= 32 || /* width cm & mm values disagree by factor >2 --> use cm values */ - u2 <= 8 || u2 >= 32 || /* dto, height */ - mi->width_mm < 100 || /* too small to be true... */ - mi->height_mm < 100 - ) { - ADD2LOG(" ddc: strange size data (%ux%u mm^2), trying cm values\n", mi->width_mm, mi->height_mm); - /* ok, try cm values */ - if(width_mm && height_mm) { - u = (width_mm * mi->height * 16) / (height_mm * mi->width); - if(u > 8 && u < 32 && width_mm >= 100 && height_mm >= 100) { - mi->width_mm = width_mm; - mi->height_mm = height_mm; + for(u = 0; u < mi_cnt; u++) { + mi = mi_list[u]; + + mi->min_vsync = min_vsync; + mi->max_vsync = max_vsync; + mi->min_hsync = min_hsync; + mi->max_hsync = max_hsync; + + mi->name = new_str(name); + mi->vendor = new_str(vendor); + mi->serial = new_str(serial); + } + + if(mi_cnt) { + qsort(mi_list, mi_cnt, sizeof *mi_list, (int (*)(const void *, const void *)) mi_cmp); + + for(i = 0; i < mi_cnt; i++) { + mi = mi_list[i]; + + mdetail = hd->detail && hd->detail->type == hd_detail_monitor ? &hd->detail->monitor : NULL; + + hd->detail = new_mem(sizeof *hd->detail); + hd->detail->type = hd_detail_monitor; + hd->detail->monitor.data = mi; + hd->detail->monitor.next = mdetail; + + hd->serial = new_str(mi->serial); + hd->vendor.name = new_str(mi->vendor); + hd->device.name = new_str(mi->name); + + if(mi->width && mi->height) { + for(res = hd->res; res; res = res->next) { + if( + res->any.type == res_monitor && + res->monitor.width == mi->width && + res->monitor.height == mi->height + ) break; + } + /* actually we could calculate the vsync value */ + if(!res) add_monitor_res(hd, mi->width, mi->height, 60, 0); + + /* do some sanity checks on display size, see bugs 155096, 186096, 213630 */ + if(mi->width_mm && mi->height_mm) { + u = (mi->width_mm * mi->height * 16) / (mi->height_mm * mi->width); + u1 = width_mm ? (width_mm * 16) / mi->width_mm : 16; + u2 = height_mm ? (height_mm * 16) / mi->height_mm : 16; + if( + u <= 8 || u >= 32 || /* allow 1:2 distortion */ + u1 <= 8 || u1 >= 32 || /* width cm & mm values disagree by factor >2 --> use cm values */ + u2 <= 8 || u2 >= 32 || /* dto, height */ + mi->width_mm < 100 || /* too small to be true... */ + mi->height_mm < 100 + ) { + ADD2LOG(" ddc: strange size data (%ux%u mm^2), trying cm values\n", mi->width_mm, mi->height_mm); + /* ok, try cm values */ + if(width_mm && height_mm) { + u = (width_mm * mi->height * 16) / (height_mm * mi->width); + if(u > 8 && u < 32 && width_mm >= 100 && height_mm >= 100) { + mi->width_mm = width_mm; + mi->height_mm = height_mm; + } + } + /* could not fix, clear */ + if(u <= 8 || u >= 32 || mi->width_mm < 100 || mi->height_mm < 100) { + ADD2LOG(" ddc: cm values (%ux%u mm^2) didn't work either - giving up\n", width_mm, height_mm); + mi->width_mm = mi->height_mm = 0; } - } - /* could not fix, clear */ - if(u <= 8 || u >= 32 || mi->width_mm < 100 || mi->height_mm < 100) { - ADD2LOG(" ddc: cm values (%ux%u mm^2) didn't work either - giving up\n", width_mm, height_mm); - mi->width_mm = mi->height_mm = 0; } } } } + mi = mi_list[0]; + if(mi->width_mm && mi->height_mm) { res = add_res_entry(&hd->res, new_mem(sizeof *res)); res->size.type = res_size; @@ -566,6 +618,10 @@ ADD2LOG("----- DDC info end -----\n"); } } + + free_mem(serial); + free_mem(vendor); + free_mem(name); } void add_monitor_res(hd_t *hd, unsigned width, unsigned height, unsigned vfreq, unsigned il) diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/src/ids/src/x11.amd64 new/hwinfo-13.46/src/ids/src/x11.amd64 --- old/hwinfo-13.45/src/ids/src/x11.amd64 2007-08-20 17:39:54.000000000 +0200 +++ new/hwinfo-13.46/src/ids/src/x11.amd64 2007-08-21 12:11:44.000000000 +0200 @@ -3459,11 +3459,6 @@ +driver.xfree 4|nv vendor.id pci 0x10de -&device.id pci 0x0429 -+device.name Quadro NVS 140M -+driver.xfree 4|nv - - vendor.id pci 0x10de &device.id pci 0x042a +device.name Quadro NVS 130M +driver.xfree 4|nv diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/src/ids/src/x11.i386 new/hwinfo-13.46/src/ids/src/x11.i386 --- old/hwinfo-13.45/src/ids/src/x11.i386 2007-08-20 17:39:55.000000000 +0200 +++ new/hwinfo-13.46/src/ids/src/x11.i386 2007-08-21 12:11:45.000000000 +0200 @@ -3459,11 +3459,6 @@ +driver.xfree 4|nv vendor.id pci 0x10de -&device.id pci 0x0429 -+device.name Quadro NVS 140M -+driver.xfree 4|nv - - vendor.id pci 0x10de &device.id pci 0x042a +device.name Quadro NVS 130M +driver.xfree 4|nv diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/src/ids/src/x11.ia64 new/hwinfo-13.46/src/ids/src/x11.ia64 --- old/hwinfo-13.45/src/ids/src/x11.ia64 2007-08-20 17:39:55.000000000 +0200 +++ new/hwinfo-13.46/src/ids/src/x11.ia64 2007-08-21 12:11:46.000000000 +0200 @@ -3082,11 +3082,6 @@ +driver.xfree 4|nv vendor.id pci 0x10de -&device.id pci 0x0429 -+device.name Quadro NVS 140M -+driver.xfree 4|nv - - vendor.id pci 0x10de &device.id pci 0x042a +device.name Quadro NVS 130M +driver.xfree 4|nv diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/src/ids/src/x11.ppc new/hwinfo-13.46/src/ids/src/x11.ppc --- old/hwinfo-13.45/src/ids/src/x11.ppc 2007-08-20 17:39:56.000000000 +0200 +++ new/hwinfo-13.46/src/ids/src/x11.ppc 2007-08-21 12:11:46.000000000 +0200 @@ -2915,11 +2915,6 @@ +driver.xfree 4|nv vendor.id pci 0x10de -&device.id pci 0x0429 -+device.name Quadro NVS 140M -+driver.xfree 4|nv - - vendor.id pci 0x10de &device.id pci 0x042a +device.name Quadro NVS 130M +driver.xfree 4|nv diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/hwinfo-13.45/VERSION new/hwinfo-13.46/VERSION --- old/hwinfo-13.45/VERSION 2007-08-20 15:18:21.000000000 +0200 +++ new/hwinfo-13.46/VERSION 2007-08-21 11:32:42.000000000 +0200 @@ -1 +1 @@ -13.45 +13.46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... --------------------------------------------------------------------- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org