diff --git a/README.md b/README.md index 9a2712bb..006234b2 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,21 @@ which are not present in regular wine, and always report such issues to us Included bugfixes and improvements ---------------------------------- -Wine-Compholio contains fixes for the following Wine bugs: +Fixed bugs for the next release (4): + +* Other Pipelight-specific enhancements +* Some applications neeed kernel32.GetFinalPathNameByHandle ([Wine Bug #36073](http://bugs.winehq.org/show_bug.cgi?id=36073 "OneDrive crashes on unimplemented function KERNEL32.dll.GetFinalPathNameByHandleW")) +* Support for DwmInvalidateIconicBitmaps ([Wine Bug #32977](http://bugs.winehq.org/show_bug.cgi?id=32977 "Solidworks 2012 needs unimplemented function dwmapi.dll.DwmInvalidateIconicBitmaps (Win7 mode)")) +* nVidia driver for high-end laptop cards does not list all supported resolutions + + +Fixed bugs in Wine-Compholio 1.7.24 (45): * ATL IOCS data should not be stored in GWLP_USERDATA ([Wine Bug #21767](http://bugs.winehq.org/show_bug.cgi?id=21767 "JLC's Internet TV crashes on startup")) * Add Dynamic DST exceptions for Israel Standard Time ([Wine Bug #36374](http://bugs.winehq.org/show_bug.cgi?id=36374 "Israel timezone handled incorrectly")) +* Add default ACLs for user shell folders * Add implementation of WTSEnumerateProcessesW ([Wine Bug #29903](http://bugs.winehq.org/show_bug.cgi?id=29903 "Some Microsoft debuggers fail to enumerate processes due to wtsapi32.WTSEnumerateProcessesW() being a stub (Microsoft Visual Studio 2005, DbgCLR from .NET 2.0 SDK)")) +* Add support for Dynamic DST (daylight saving time) information in registry * Add support for extra large and jumbo icon lists in shell32 ([Wine Bug #24721](http://bugs.winehq.org/show_bug.cgi?id=24721 "Explorer++ crashes when choosing to view large icons or extra large icons")) * Allow special characters in pipe names ([Wine Bug #28995](http://bugs.winehq.org/show_bug.cgi?id=28995 "Unable to use named pipes with \">\" character in the name")) * Audio stuttering and performance drops in multiple applications ([Wine Bug #30639](http://bugs.winehq.org/show_bug.cgi?id=30639 "Audio stuttering and performance drops in Star Wolves 3")) @@ -29,14 +39,18 @@ Wine-Compholio contains fixes for the following Wine bugs: * Implement LoadIconMetric function ([Wine Bug #35375](http://bugs.winehq.org/show_bug.cgi?id=35375 "Multiple applications need Vista+ API COMCTL32.dll.380 a.k.a. 'LoadIconMetric' (Solidworks 2013 systray monitor, Microsoft One/SkyDrive)")) * Implement a Microsoft Yahei replacement font ([Wine Bug #13829](http://bugs.winehq.org/show_bug.cgi?id=13829 "Wine does not have CJK fonts")) * Implement an Arial replacement font ([Wine Bug #32323](http://bugs.winehq.org/show_bug.cgi?id=32323 "Netflix (Silverlight 4.x) and several .NET Framework 3.x/4.0 WPF apps require either Arial or Verdana to be installed")) +* Lockfree algorithm for filedescriptor cache (improves file access speed) * Make it possible to change media center / tablet pc status ([Wine Bug #18732](http://bugs.winehq.org/show_bug.cgi?id=18732 "Microsoft Experience Pack for Tablet PC 1 refuses to install")) * Need for Speed 3 installer requires devices in HKEY_DYN_DATA ([Wine Bug #7115](http://bugs.winehq.org/show_bug.cgi?id=7115 "Need for Speed III installer fails in Win9X mode, reporting \"Could not get 'HardWareKey' value\" (active PnP device keys in 'HKEY_DYN_DATA\\\\Config Manager\\\\Enum' missing)")) +* ~~Old games cannot locate software-only renderer~~ ([Wine Bug #32581](http://bugs.winehq.org/show_bug.cgi?id=32581 "Invalid dwFlags of reference rasterizer's HAL D3DDEVICEDESC")) +* ~~Other Pipelight specific enhancements~~ +* Reduced SetTimer minimum value from 10 ms to 5 ms (improves Silverlight framerates) * Return correct IMediaSeeking stream positions in quartz ([Wine Bug #23174](http://bugs.winehq.org/show_bug.cgi?id=23174 "Fallout 3: Diologue and Video/sound issues")) +* SO_CONNECT_TIME returns the appropriate time * Set ldr.EntryPoint for main executable ([Wine Bug #33034](http://bugs.winehq.org/show_bug.cgi?id=33034 "Many GFWL (Games For Windows Live) 1.x/2.x/3.x games crash or exit silently on startup (DiRT 2/3, GTA IV Steam)")) -* Some applications neeed kernel32.GetFinalPathNameByHandle ([Wine Bug #36073](http://bugs.winehq.org/show_bug.cgi?id=36073 "OneDrive crashes on unimplemented function KERNEL32.dll.GetFinalPathNameByHandleW")) * Support for AllocateAndGetTcpExTableFromStack ([Wine Bug #34372](http://bugs.winehq.org/show_bug.cgi?id=34372 "Add missing function AllocateAndGetTcpExTableFromStack() to iphlpapi.dll")) -* Support for DwmInvalidateIconicBitmaps ([Wine Bug #32977](http://bugs.winehq.org/show_bug.cgi?id=32977 "Solidworks 2012 needs unimplemented function dwmapi.dll.DwmInvalidateIconicBitmaps (Win7 mode)")) * Support for GetSystemTimes ([Wine Bug #19813](http://bugs.winehq.org/show_bug.cgi?id=19813 "Voddler needs GetSystemTimes to run")) +* Support for GetVolumePathName * Support for ITextRange, ITextFont and ITextPara ([Wine Bug #18303](http://bugs.winehq.org/show_bug.cgi?id=18303 "Adobe Acrobat Pro 7: Crashes when selecting the \"edit\" menu while having a file open.")) * Support for Junction Points ([Wine Bug #12401](http://bugs.winehq.org/show_bug.cgi?id=12401 "Support junction points, i.e. DeviceIoCtl(FSCTL_SET_REPARSE_POINT/FSCTL_GET_REPARSE_POINT)")) * Support for NtSetInformationFile class FileDispositionInformation ([Wine Bug #30397](http://bugs.winehq.org/show_bug.cgi?id=30397 "Multiple applications need support for NtSetInformationFile class FileDispositionInformation (Cygwin installer, Stylizer 5.x Visual CSS editor, Spoon Studio 2011 (ex Xenocode) application sandboxing scheme)")) @@ -52,19 +66,8 @@ Wine-Compholio contains fixes for the following Wine bugs: * Support for ws2_32.inet_pton ([Wine Bug #36713](http://bugs.winehq.org/show_bug.cgi?id=36713 "Watch_Dogs requires ws2_32.inet_pton")) * Use manual relay for RunDLL_CallEntry16 in shell32 ([Wine Bug #23033](http://bugs.winehq.org/show_bug.cgi?id=23033 "Tages Protection v5.x: games report \"DLL not found shell.dll16.dll\" (Runaway 2: The Dream Of The Turtle, ...)")) * Workaround for TransactNamedPipe not being supported ([Wine Bug #17273](http://bugs.winehq.org/show_bug.cgi?id=17273 "Many apps and games need SetNamedPipeHandleState implementation (support for named pipe message mode)(FireFox+Flash, Win8/NET 4.x SDK/vcrun2012, WiX installers)")) - -Besides that the following additional changes are included: - -* Add default ACLs for user shell folders -* Add support for Dynamic DST (daylight saving time) information in registry -* Lockfree algorithm for filedescriptor cache (improves file access speed) -* Other Pipelight-specific enhancements -* Reduced SetTimer minimum value from 10 ms to 5 ms (improves Silverlight framerates) -* SO_CONNECT_TIME returns the appropriate time -* Support for GetVolumePathName * Workaround for shlwapi URLs with relative paths * XEMBED support for embedding Wine windows inside Linux applications -* nVidia driver for high-end laptop cards does not list all supported resolutions How to install Wine-Compholio diff --git a/debian/tools/README.md.in b/debian/tools/README.md.in index 0efc5104..5ecbf0d3 100644 --- a/debian/tools/README.md.in +++ b/debian/tools/README.md.in @@ -13,12 +13,6 @@ which are not present in regular wine, and always report such issues to us Included bugfixes and improvements ---------------------------------- -Wine-Compholio contains fixes for the following Wine bugs: - -{bugs} - -Besides that the following additional changes are included: - {fixes} diff --git a/debian/tools/patchupdate.py b/debian/tools/patchupdate.py index 4eac0f4b..d0d68208 100755 --- a/debian/tools/patchupdate.py +++ b/debian/tools/patchupdate.py @@ -39,21 +39,21 @@ cached_patch_result = {} cached_original_src = {} class config(object): - path_depcache = "./.depcache" - path_srccache = "./.srccache" + path_depcache = ".depcache" + path_srccache = ".srccache" - path_patches = "./patches" - path_changelog = "./debian/changelog" - path_wine = "./debian/tools/wine" + path_patches = "patches" + path_changelog = "debian/changelog" + path_wine = "debian/tools/wine" - path_template_Makefile = "./debian/tools/Makefile.in" - path_Makefile = "./patches/Makefile" + path_template_Makefile = "debian/tools/Makefile.in" + path_Makefile = "patches/Makefile" - path_README_md = "./README.md" - path_template_README_md = "./debian/tools/README.md.in" + path_README_md = "README.md" + path_template_README_md = "debian/tools/README.md.in" - path_DEVELOPER_md = "./DEVELOPER.md" - path_template_DEVELOPER_md = "./debian/tools/DEVELOPER.md.in" + path_DEVELOPER_md = "DEVELOPER.md" + path_template_DEVELOPER_md = "debian/tools/DEVELOPER.md.in" class PatchUpdaterError(RuntimeError): """Failed to update patches.""" @@ -118,20 +118,66 @@ def _winebugs_query_short_desc(bugids): result[bugid] = element.firstChild.data return result -def read_definition(filename, name_to_id = None, revision = None): +# Read information from changelog +def _read_changelog(): + with open(config.path_changelog) as fp: + for line in fp: + r = re.match("^([a-zA-Z0-9][^(]*)\((.*)\) ([^;]*)", line) + if r: yield (r.group(1).strip(), r.group(2).strip(), r.group(3).strip()) + +# Get version number of the latest stable release +def _stable_compholio_version(): + for package, version, distro in _read_changelog(): + if distro.lower() != "unreleased": + return version + +# Get latest wine commit +def _latest_wine_commit(): + if not os.path.isdir(config.path_wine): + raise PatchUpdaterError("Please create a symlink to the wine repository in %s" % config.path_wine) + commit = subprocess.check_output(["git", "rev-parse", "origin/master"], cwd=config.path_wine).strip() + assert len(commit) == 40 + return commit + +def enum_directories(revision, path): + """Enumerate all subdirectories of 'path' at a specific revision.""" + dirs = [] + + if path[0:2] == "./": + path = path[2:] + elif path[0] == "/": + raise RuntimeError("Expected relative path, not an absolute path") + + if revision is None: + for name in os.listdir(path): + if name in [".", ".."]: continue + subdirectory = os.path.join(path, name) + if not os.path.isdir(subdirectory): + continue + dirs.append((name, subdirectory)) + else: + filename = "%s:%s" % (revision, path) + with open(os.devnull, 'w') as devnull: + content = subprocess.check_output(["git", "show", filename], stderr=devnull) + lines = content.split("\n") + if not lines[0].startswith("tree ") or lines[1] != "": + raise RuntimeError("Unexpected output from 'git show %s'" % filename) + for name in lines[2:]: + if name == "" or name[-1] != "/": continue + name = name[:-1] + dirs.append((name, os.path.join(path, name))) + + return dirs + +def read_definition(revision, filename, name_to_id): """Read a definition file and return information as tuple (authors, depends, fixes).""" - filename = os.path.join(filename, "definition") + filename = "%s:%s" % (revision if revision else "", os.path.join(filename, "definition")) try: - if revision is not None: - filename = "%s:%s" % (revision, filename) - with open(os.devnull, 'w') as devnull: - content = subprocess.check_output(["git", "show", filename], stderr=devnull) - else: - with open(filename) as fp: - content = fp.read() - except IOError: - raise PatchUpaterError("Missing definition file %s" % filename) + with open(os.devnull, 'w') as devnull: + content = subprocess.check_output(["git", "show", filename], stderr=devnull) + except CalledProcessError: + raise IOError("Failed to read %s" % filename) authors = [] depends = set() @@ -153,17 +199,21 @@ def read_definition(filename, name_to_id = None, revision = None): if key == "author": if len(info.author): info.author += ", " info.author += val + elif key == "subject" or key == "title": if len(info.subject): info.subject += " " info.subject += val + elif key == "revision": if len(info.revision): info.revision += ", " info.revision += val + elif key == "depends": if name_to_id is not None: if not name_to_id.has_key(val): raise PatchUpdaterError("Definition file %s references unknown dependency %s" % (filename, val)) depends.add(name_to_id[val]) + elif key == "fixes": r = re.match("^[0-9]+$", val) if r: @@ -174,6 +224,7 @@ def read_definition(filename, name_to_id = None, revision = None): fixes.append((int(r.group(1)), r.group(2).strip())) continue fixes.append((None, val)) + else: print "WARNING: Ignoring unknown command in definition file %s: %s" % (deffile, line) @@ -181,46 +232,36 @@ def read_definition(filename, name_to_id = None, revision = None): authors.append(info) return authors, depends, fixes -def read_patchsets(directory): - """Read information about all patchsets in a given directory.""" - - def _iter_kv_from_file(filename): - """Iterate through all key/value pairs in a file.""" - with open(filename) as fp: - for line in fp: - if line.startswith("#"): - continue - tmp = line.split(":", 1) - if len(tmp) != 2: - yield None, None - else: - yield tmp[0].lower(), tmp[1].strip() +def read_patchset(revision = None): + """Read information about all patchsets for a specific revision.""" unique_id = itertools.count() all_patches = {} name_to_id = {} # Read in sorted order (to ensure created Makefile doesn't change too much) - for name in sorted(os.listdir(directory)): - if name in [".", ".."]: continue - subdirectory = os.path.join(directory, name) - if not os.path.isdir(subdirectory): continue - + for name, subdirectory in sorted(enum_directories(revision, config.path_patches)): patch = PatchSet(name) - # Enumerate .patch files in the given directory, enumerate individual patches and affected files - for f in sorted(os.listdir(subdirectory)): - if not f.endswith(".patch") or not os.path.isfile(os.path.join(subdirectory, f)): - continue - patch.files.append(f) - for p in patchutils.read_patch(os.path.join(subdirectory, f)): - patch.patches.append(p) - patch.modified_files.add(p.modified_file) + if revision is None: - # No single patch within this directory, ignore it - if len(patch.patches) == 0: - del patch - continue + # If its the latest revision, then request additional information + if not os.path.isdir(subdirectory): + raise RuntimeError("Unable to open directory %s" % subdirectory) + + # Enumerate .patch files in the given directory, enumerate individual patches and affected files + for f in sorted(os.listdir(subdirectory)): + if not f.endswith(".patch") or not os.path.isfile(os.path.join(subdirectory, f)): + continue + patch.files.append(f) + for p in patchutils.read_patch(os.path.join(subdirectory, f)): + patch.modified_files.add(p.modified_file) + patch.patches.append(p) + + # No single patch within this directory, ignore it + if len(patch.patches) == 0: + del patch + continue i = next(unique_id) all_patches[i] = patch @@ -228,8 +269,11 @@ def read_patchsets(directory): # Now read the definition files in a second step for i, patch in all_patches.iteritems(): - patch.authors, patch.depends, patch.fixes = \ - read_definition(os.path.join(directory, patch.name), name_to_id=name_to_id) + try: + patch.authors, patch.depends, patch.fixes = \ + read_definition(revision, os.path.join(config.path_patches, patch.name), name_to_id) + except IOError: + raise PatchUpaterError("Missing definition file for %s" % patch.name) return all_patches @@ -475,75 +519,93 @@ def generate_makefile(all_patches): fp.write("\ttouch %s.ok\n" % patch.name) fp.write("\n"); -def generate_markdown(all_patches): +def generate_markdown(all_patches, stable_patches, stable_compholio_version): """Generate README.md and DEVELOPER.md including information about specific patches and bugfixes.""" - # Get list of all bugs (including short_desc from Wine bugzilla) - def _all_bugs(): - all_bugs = [] - for i, patch in all_patches.iteritems(): - for bugid, bugname in patch.fixes: - if bugid is not None: all_bugs.append((bugid, bugname)) - bug_short_desc = _winebugs_query_short_desc([bugid for bugid, bugname in all_bugs]) - for bugid, bugname in sorted(all_bugs, key=lambda x: x[1]): - if bugid is None: continue + def _format_bug(mode, bugid, bugname): + if bugid is not None: short_desc = bug_short_desc[bugid] if bugname is None: bugname = short_desc - yield "%s ([Wine Bug #%d](http://bugs.winehq.org/show_bug.cgi?id=%d \"%s\"))" % \ - (bugname, bugid, bugid, short_desc.replace("\\", "\\\\").replace("\"", "\\\"")) + if mode < 0: bugname = "~~%s~~" % bugname + if bugid is None: return "* %s" % bugname + return "* %s ([Wine Bug #%d](http://bugs.winehq.org/show_bug.cgi?id=%d \"%s\"))" % \ + (bugname, bugid, bugid, short_desc.replace("\\", "\\\\").replace("\"", "\\\"")) - # Get list of all fixes - def _all_fixes(): - all_fixes = [] - for i, patch in all_patches.iteritems(): - for bugid, bugname in patch.fixes: - if bugid is None: all_fixes.append((bugid, bugname)) - for bugid, bugname in sorted(all_fixes, key=lambda x: x[1]): - yield bugname + all_bugids = set() + all_fixes = {} - # Read information from changelog - def _read_changelog(): - with open(config.path_changelog) as fp: - for line in fp: - r = re.match("^([a-zA-Z0-9][^(]*)\((.*)\) ([^;]*)", line) - if r: yield (r.group(1).strip(), r.group(2).strip(), r.group(3).strip()) + # Get fixes for current version + for i, patch in all_patches.iteritems(): + for bugid, bugname in patch.fixes: + if bugid is not None: all_bugids.add(bugid) + key = bugid if bugid is not None else bugname + all_fixes[key] = [1, bugid, bugname] - # Get version number of the latest stable release - def _latest_stable_version(): - for package, version, distro in _read_changelog(): - if distro.lower() != "unreleased": - return version + # Compare with fixes for latest stable version + for i, patch in stable_patches.iteritems(): + for bugid, bugname in patch.fixes: + if bugid is not None: all_bugids.add(bugid) + key = bugid if bugid is not None else bugname + if all_fixes.has_key(key): + all_fixes[key][0] = 0 + else: + all_fixes[key] = [-1, bugid, bugname] - # Create enumeration from list - def _enum(x): - return "* " + "\n* ".join(x) + # Generate lists for all new and old fixes + new_fixes = [(mode, bugid, bugname) for dummy, (mode, bugid, bugname) in + all_fixes.iteritems() if mode > 0] + old_fixes = [(mode, bugid, bugname) for dummy, (mode, bugid, bugname) in + all_fixes.iteritems() if mode <= 0] + # Query information from bugzilla + bug_short_desc = _winebugs_query_short_desc(all_bugids) + + # Generate information for current version + lines = [] + if len(new_fixes): + lines.append("Fixed bugs for the next release (%d):" % len(new_fixes)) + lines.append("") + for mode, bugid, bugname in sorted(new_fixes, key=lambda x: x[2]): + lines.append(_format_bug(mode, bugid, bugname)) + lines.append("") + lines.append("") + lines.append("Fixed bugs in Wine-Compholio %s (%d):" % (stable_compholio_version, len(old_fixes))) + lines.append("") + for mode, bugid, bugname in sorted(old_fixes, key=lambda x: x[2]): + lines.append(_format_bug(mode, bugid, bugname)) + + # Update README.md with open(config.path_template_README_md) as template_fp: template = template_fp.read() with open(config.path_README_md, "w") as fp: - fp.write(template.format(bugs=_enum(_all_bugs()), fixes=_enum(_all_fixes()))) + fp.write(template.format(fixes="\n".join(lines))) + # Update DEVELOPER.md with open(config.path_template_DEVELOPER_md) as template_fp: template = template_fp.read() with open(config.path_DEVELOPER_md, "w") as fp: - fp.write(template.format(version=_latest_stable_version())) + fp.write(template.format(version=stable_compholio_version)) if __name__ == "__main__": - - # Get the latest wine commit (sha1) - if not os.path.isdir(config.path_wine): - raise RuntimeError("Please create a symlink to the wine repository in %s" % config.path_wine) - latest_wine_commit = subprocess.check_output(["git", "rev-parse", "origin/master"], cwd=config.path_wine).strip() - assert len(latest_wine_commit) == 40 - try: - all_patches = read_patchsets(config.path_patches) + + # Get information about Wine and Compholio version + latest_wine_commit = _latest_wine_commit() + stable_compholio_version = _stable_compholio_version() + + # Read current and stable patches + all_patches = read_patchset() + stable_patches = read_patchset(revision="v%s" % stable_compholio_version) + + # Check dependencies verify_dependencies(all_patches) + + # Update Makefile, README.md and DEVELOPER.md + generate_makefile(all_patches) + generate_markdown(all_patches, stable_patches, stable_compholio_version) + except PatchUpdaterError as e: print "" print "ERROR: %s" % e print "" exit(1) - - generate_makefile(all_patches) - generate_markdown(all_patches)