From ede4e23677a2a05ac9b87c4db1a4d35920c3e607 Mon Sep 17 00:00:00 2001
From: Jo-Philipp Wich <jow@openwrt.org>
Date: Thu, 15 Nov 2012 20:17:49 +0000
Subject: [PATCH] opkg: various additions - only wrap package descriptions when
 outputting to a tty, simplifies parsing descriptions with external utils -
 introduce -i (--nocase) flag which makes all matching operations case
 insensitive - introduce "find" command which searches package names and
 descriptions (e.g. opkg -i find "*autoconfig*")

SVN-Revision: 34202
---
 package/opkg/Makefile                         |   2 +-
 .../040-wrap-descriptions-only-on-ttys.patch  |  31 ++++
 .../050-add-case-insensitive-flag.patch       | 169 ++++++++++++++++++
 .../opkg/patches/060-add-find-command.patch   |  58 ++++++
 4 files changed, 259 insertions(+), 1 deletion(-)
 create mode 100644 package/opkg/patches/040-wrap-descriptions-only-on-ttys.patch
 create mode 100644 package/opkg/patches/050-add-case-insensitive-flag.patch
 create mode 100644 package/opkg/patches/060-add-find-command.patch

diff --git a/package/opkg/Makefile b/package/opkg/Makefile
index a41127ab2b7..6407ab451f4 100644
--- a/package/opkg/Makefile
+++ b/package/opkg/Makefile
@@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/version.mk
 PKG_NAME:=opkg
 PKG_REV:=618
 PKG_VERSION:=$(PKG_REV)
-PKG_RELEASE:=2
+PKG_RELEASE:=3
 
 PKG_SOURCE_PROTO:=svn
 PKG_SOURCE_VERSION:=$(PKG_REV)
diff --git a/package/opkg/patches/040-wrap-descriptions-only-on-ttys.patch b/package/opkg/patches/040-wrap-descriptions-only-on-ttys.patch
new file mode 100644
index 00000000000..95406687b6a
--- /dev/null
+++ b/package/opkg/patches/040-wrap-descriptions-only-on-ttys.patch
@@ -0,0 +1,31 @@
+--- a/libopkg/pkg_parse.c
++++ b/libopkg/pkg_parse.c
+@@ -20,6 +20,7 @@
+ 
+ #include <stdio.h>
+ #include <ctype.h>
++#include <unistd.h>
+ 
+ #include "pkg.h"
+ #include "opkg_utils.h"
+@@ -239,10 +240,16 @@ pkg_parse_line(void *ptr, const char *li
+ 
+ 	case ' ':
+ 		if ((mask & PFM_DESCRIPTION) && reading_description) {
+-			pkg->description = xrealloc(pkg->description,
+-						strlen(pkg->description)
+-						+ 1 + strlen(line) + 1);
+-			strcat(pkg->description, "\n");
++			if (isatty(1)) {
++				pkg->description = xrealloc(pkg->description,
++							strlen(pkg->description)
++							+ 1 + strlen(line) + 1);
++				strcat(pkg->description, "\n");
++			} else {
++				pkg->description = xrealloc(pkg->description,
++							strlen(pkg->description)
++							+ 1 + strlen(line));
++			}
+ 			strcat(pkg->description, (line));
+ 			goto dont_reset_flags;
+ 		} else if ((mask & PFM_CONFFILES) && reading_conffiles) {
diff --git a/package/opkg/patches/050-add-case-insensitive-flag.patch b/package/opkg/patches/050-add-case-insensitive-flag.patch
new file mode 100644
index 00000000000..4b9215b87ac
--- /dev/null
+++ b/package/opkg/patches/050-add-case-insensitive-flag.patch
@@ -0,0 +1,169 @@
+--- a/libopkg/opkg_cmd.c
++++ b/libopkg/opkg_cmd.c
+@@ -436,7 +436,7 @@ opkg_configure_packages(char *pkg_name)
+      for(i = 0; i < ordered->len; i++) {
+ 	  pkg = ordered->pkgs[i];
+ 
+-	  if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
++	  if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
+ 	       continue;
+ 
+ 	  if (pkg->state_status == SS_UNPACKED) {
+@@ -610,7 +610,7 @@ opkg_list_cmd(int argc, char **argv)
+      for (i=0; i < available->len; i++) {
+ 	  pkg = available->pkgs[i];
+ 	  /* if we have package name or pattern and pkg does not match, then skip it */
+-	  if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
++	  if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
+ 	       continue;
+           print_pkg(pkg);
+      }
+@@ -637,7 +637,7 @@ opkg_list_installed_cmd(int argc, char *
+      for (i=0; i < available->len; i++) {
+ 	  pkg = available->pkgs[i];
+ 	  /* if we have package name or pattern and pkg does not match, then skip it */
+-	  if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
++	  if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
+ 	       continue;
+           print_pkg(pkg);
+      }
+@@ -666,7 +666,7 @@ opkg_list_changed_conffiles_cmd(int argc
+      for (i=0; i < available->len; i++) {
+ 	  pkg = available->pkgs[i];
+ 	  /* if we have package name or pattern and pkg does not match, then skip it */
+-	  if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
++	  if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
+ 	    continue;
+ 	  if (nv_pair_list_empty(&pkg->conffiles))
+ 	    continue;
+@@ -722,7 +722,7 @@ opkg_info_status_cmd(int argc, char **ar
+ 
+      for (i=0; i < available->len; i++) {
+ 	  pkg = available->pkgs[i];
+-	  if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
++	  if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) {
+ 	       continue;
+ 	  }
+ 
+@@ -792,7 +792,7 @@ opkg_remove_cmd(int argc, char **argv)
+      for (i=0; i<argc; i++) {
+         for (a=0; a<available->len; a++) {
+             pkg = available->pkgs[a];
+-	    if (fnmatch(argv[i], pkg->name, 0)) {
++	    if (fnmatch(argv[i], pkg->name, conf->nocase)) {
+                continue;
+             }
+             if (conf->restrict_to_default_dest) {
+@@ -926,7 +926,7 @@ opkg_depends_cmd(int argc, char **argv)
+ 		for (j=0; j<available_pkgs->len; j++) {
+ 			pkg = available_pkgs->pkgs[j];
+ 
+-			if (fnmatch(argv[i], pkg->name, 0) != 0)
++			if (fnmatch(argv[i], pkg->name, conf->nocase) != 0)
+ 				continue;
+ 
+ 			depends_count = pkg->depends_count +
+@@ -1147,9 +1147,9 @@ opkg_what_provides_replaces_cmd(enum wha
+ 			      ((what_field_type == WHATPROVIDES)
+ 			       ? pkg->provides[k]
+ 			       : pkg->replaces[k]);
+-			 if (fnmatch(target, apkg->name, 0) == 0) {
++			 if (fnmatch(target, apkg->name, conf->nocase) == 0) {
+ 			      opkg_msg(NOTICE, "    %s", pkg->name);
+-			      if (strcmp(target, apkg->name) != 0)
++			      if ((conf->nocase ? strcasecmp(target, apkg->name) : strcmp(target, apkg->name)) != 0)
+ 				   opkg_msg(NOTICE, "\t%s %s\n",
+ 						   rel_str, apkg->name);
+ 			      opkg_message(NOTICE, "\n");
+@@ -1200,7 +1200,7 @@ opkg_search_cmd(int argc, char **argv)
+ 
+ 	  for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
+ 	       installed_file = (char *)iter->data;
+-	       if (fnmatch(argv[0], installed_file, 0)==0)
++	       if (fnmatch(argv[0], installed_file, conf->nocase)==0)
+ 	            print_pkg(pkg);
+ 	  }
+ 
+--- a/libopkg/opkg_conf.c
++++ b/libopkg/opkg_conf.c
+@@ -62,6 +62,7 @@ opkg_option_t options[] = {
+ 	  { "noaction", OPKG_OPT_TYPE_BOOL, &_conf.noaction },
+ 	  { "download_only", OPKG_OPT_TYPE_BOOL, &_conf.download_only },
+ 	  { "nodeps", OPKG_OPT_TYPE_BOOL, &_conf.nodeps },
++	  { "nocase", OPKG_OPT_TYPE_BOOL, &_conf.nocase },
+ 	  { "offline_root", OPKG_OPT_TYPE_STRING, &_conf.offline_root },
+ 	  { "overlay_root", OPKG_OPT_TYPE_STRING, &_conf.overlay_root },
+ 	  { "proxy_passwd", OPKG_OPT_TYPE_STRING, &_conf.proxy_passwd },
+--- a/libopkg/opkg_conf.h
++++ b/libopkg/opkg_conf.h
+@@ -24,6 +24,7 @@ extern opkg_conf_t *conf;
+ #include "config.h"
+ 
+ #include <stdarg.h>
++#include <fnmatch.h> /* FNM_CASEFOLD */
+ 
+ #include "hash_table.h"
+ #include "pkg_src_list.h"
+@@ -79,6 +80,7 @@ struct opkg_conf
+      int force_remove;
+      int check_signature;
+      int nodeps; /* do not follow dependencies */
++     int nocase; /* perform case insensitive matching */
+      char *offline_root;
+      char *overlay_root;
+      int query_all;
+--- a/src/opkg-cl.c
++++ b/src/opkg-cl.c
+@@ -47,6 +47,7 @@ enum {
+ 	ARGS_OPT_NOACTION,
+ 	ARGS_OPT_DOWNLOAD_ONLY,
+ 	ARGS_OPT_NODEPS,
++	ARGS_OPT_NOCASE,
+ 	ARGS_OPT_AUTOREMOVE,
+ 	ARGS_OPT_CACHE,
+ };
+@@ -86,6 +87,7 @@ static struct option long_options[] = {
+ 	{"noaction", 0, 0, ARGS_OPT_NOACTION},
+ 	{"download-only", 0, 0, ARGS_OPT_DOWNLOAD_ONLY},
+ 	{"nodeps", 0, 0, ARGS_OPT_NODEPS},
++	{"nocase", 0, 0, ARGS_OPT_NOCASE},
+ 	{"offline", 1, 0, 'o'},
+ 	{"offline-root", 1, 0, 'o'},
+ 	{"add-arch", 1, 0, ARGS_OPT_ADD_ARCH},
+@@ -107,7 +109,7 @@ args_parse(int argc, char *argv[])
+ 	char *tuple, *targ;
+ 
+ 	while (1) {
+-		c = getopt_long_only(argc, argv, "Ad:f:no:p:t:vV::",
++		c = getopt_long_only(argc, argv, "Ad:f:ino:p:t:vV::",
+ 				long_options, &option_index);
+ 		if (c == -1)
+ 			break;
+@@ -122,6 +124,9 @@ args_parse(int argc, char *argv[])
+ 		case 'f':
+ 			conf->conf_file = xstrdup(optarg);
+ 			break;
++		case 'i':
++			conf->nocase = FNM_CASEFOLD;
++			break;
+ 		case 'o':
+ 			conf->offline_root = xstrdup(optarg);
+ 			break;
+@@ -176,6 +181,9 @@ args_parse(int argc, char *argv[])
+ 		case ARGS_OPT_NODEPS:
+ 			conf->nodeps = 1;
+ 			break;
++		case ARGS_OPT_NOCASE:
++			conf->nocase = FNM_CASEFOLD;
++			break;
+ 		case ARGS_OPT_ADD_ARCH:
+ 		case ARGS_OPT_ADD_DEST:
+ 			tuple = xstrdup(optarg);
+@@ -287,6 +295,7 @@ usage()
+ 	printf("\t--noaction		No action -- test only\n");
+ 	printf("\t--download-only	No action -- download only\n");
+ 	printf("\t--nodeps		Do not follow dependencies\n");
++	printf("\t--nocase		Perform case insensitive pattern matching\n");
+ 	printf("\t--force-removal-of-dependent-packages\n");
+ 	printf("\t			Remove package and all dependencies\n");
+ 	printf("\t--autoremove		Remove packages that were installed\n");
diff --git a/package/opkg/patches/060-add-find-command.patch b/package/opkg/patches/060-add-find-command.patch
new file mode 100644
index 00000000000..219df101870
--- /dev/null
+++ b/package/opkg/patches/060-add-find-command.patch
@@ -0,0 +1,58 @@
+--- a/libopkg/opkg_cmd.c
++++ b/libopkg/opkg_cmd.c
+@@ -594,7 +594,7 @@ opkg_download_cmd(int argc, char **argv)
+ 
+ 
+ static int
+-opkg_list_cmd(int argc, char **argv)
++opkg_list_find_cmd(int argc, char **argv, int use_desc)
+ {
+      int i;
+      pkg_vec_t *available;
+@@ -612,6 +612,9 @@ opkg_list_cmd(int argc, char **argv)
+ 	  /* if we have package name or pattern and pkg does not match, then skip it */
+ 	  if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
+ 	       continue;
++	  if (pkg_name && use_desc && pkg->description &&
++	      fnmatch(pkg_name, pkg->description, conf->nocase))
++	       continue;
+           print_pkg(pkg);
+      }
+      pkg_vec_free(available);
+@@ -619,6 +622,18 @@ opkg_list_cmd(int argc, char **argv)
+      return 0;
+ }
+ 
++static int
++opkg_list_cmd(int argc, char **argv)
++{
++	return opkg_list_find_cmd(argc, argv, 0);
++}
++
++static int
++opkg_find_cmd(int argc, char **argv)
++{
++	return opkg_list_find_cmd(argc, argv, 1);
++}
++
+ 
+ static int
+ opkg_list_installed_cmd(int argc, char **argv)
+@@ -1262,6 +1277,7 @@ static opkg_cmd_t cmds[] = {
+      {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd, PFM_DESCRIPTION|PFM_SOURCE},
+      {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd, PFM_DESCRIPTION|PFM_SOURCE},
+      {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd, PFM_DESCRIPTION|PFM_SOURCE},
++     {"find", 1, (opkg_cmd_fun_t)opkg_find_cmd, PFM_SOURCE},
+      {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd, PFM_DESCRIPTION|PFM_SOURCE},
+      {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE},
+      {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE},
+--- a/src/opkg-cl.c
++++ b/src/opkg-cl.c
+@@ -246,6 +246,7 @@ usage()
+ 	printf("\tlist-changed-conffiles	List user modified configuration files\n");
+ 	printf("\tfiles <pkg>		List files belonging to <pkg>\n");
+ 	printf("\tsearch <file|regexp>	List package providing <file>\n");
++	printf("\tfind <regexp>		List packages whose name or description matches <regexp>\n");
+ 	printf("\tinfo [pkg|regexp]	Display all info for <pkg>\n");
+ 	printf("\tstatus [pkg|regexp]	Display all status for <pkg>\n");
+ 	printf("\tdownload <pkg>		Download <pkg> to current directory\n");