[MERGE] win98 support

John Arbash Meinel john at arbash-meinel.com
Thu Feb 1 19:24:05 GMT 2007


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Alexander Belchenko wrote:
> This patch provide support for OS Windows 98.
> bzr already mostly works on win98 but have some
> incompatibility in the methods how bzr determine
> some info about platform itself.
> 
> This patch change and fix next things:
> 
> 1) get home location to store .bzr.log. Now it try to store .bzr.log
> on any Windows in My Documents folder. I hope it will simplify things a bit.
> 2) get location to store and retrieve configuration files (bazaar.conf,
> locations.conf; default folder with plugins)
> 3) auto_user_id rely on Win32 API in first place, and only fall back
> to environment variables in exclusive case.
> 4) fix some problems (related to win98) with win32 installers.
> 
> As result this patch raise one strong dependency for Windows:
> bzr need to have ctypes installed. Note that Python 2.5 ships
> with ctypes inside. Also note that Python 2.5 is the last
> release that supports Windows 98.
> 
> I test it on the win98 machine that I have access to.
> On demand I can upload new standalone installer with win98
> support for testing by people on their machines.
> 
> Here the log of changes:
> 
>  2246 Alexander Belchenko	2007-01-30
>       win32utils: Windows-specific functions that use Win32 API via ctypes
> 
>  2247 Alexander Belchenko	2007-01-30
>       trace.py: open_tracefile(): win98-compatible detection of location for .bzr.log
> 
>       It's also change default location of .bzr.log on Windows 2000/XP as well:
>       now it in user's My Documents folder, so it's much better
>       for users without administarator priveleges.
> 
>       Also workaround win32-specific issue with file.tell().
> 
>  2248 Alexander Belchenko	2007-01-30
>       config.py: changing _auto_user_id() and config_dir() to use functions from win32utils
> 
>  2249 Alexander Belchenko	2007-01-30
>       setup.py: fix plain 'python setup.py install' for win98
> 
>  2250 Alexander Belchenko	2007-01-30
>       bzr-win32-bdist-postinstall.py: good win98 support
> 
>  2251 Alexander Belchenko	2007-01-30
>       osutils.py: terminal_width() now use win32utils.get_console_size()
> 
>  2252 Alexander Belchenko	2007-01-31
>       standalone installer: win98 support
> 
>  2253 Alexander Belchenko	2007-01-31
>       bzr_postinstall.py: on win98 path added to autoexec.bat should have 8.3 form
> 



v- We don't generally do "Author:" tags. There isn't a strict style
statement, and I've noticed that Robert tends to put his name.

But the general feeling is that we have a VCS for that, and otherwise
the Author tags are never really very accurate. (Nobody removes a name
when someones code is removed, half the people don't add their names, etc).

This isn't something I would block, just something to make a comment about.


...

v- You might also want to look at 'os.name'. But as long as this works
for you.

+
+# Windows version
+if sys.platform == 'win32':
+    _major,_minor,_build,_platform,_text = sys.getwindowsversion()

v- hmm.. a bare Exception isn't very nice, but whatever. I would also
recommend "Unknown platform (unsupported): %s' % (sys.getwindowsversion(),)

Or something like that to make it clear what is going on, and maybe give
the user a way to figure out a work around.

Also, using "if _platform not in (0, 1): _platform == 'Windows NT'
doesn't seem quite right.
What is Vista going to return?

You may want 'os.name' since it might be more accurate for your purposes.

+    if _platform == 0:
+        raise Exception('This platform does not supported!')
+    elif _platform == 1:
+        winver = 'Windows 98'
+    else:
+        winver = 'Windows NT'
+else:
+    winver = None
+

 # We can cope without it; use a separate variable to help pyflakes
 try:
- -   import ctypes
- -   has_ctypes = True
+    import ctypes
+    has_ctypes = True
 except ImportError:
     has_ctypes = False
- -
- -
+else:
+    if winver == 'Windows 98':
+        create_buffer = ctypes.create_string_buffer
+        suffix = 'A'
+    else:
+        create_buffer = ctypes.create_unicode_buffer
+        suffix = 'W'
+
+
+# Special Win32 API constants
+# Handles of std streams
 WIN32_STDIN_HANDLE = -10
 WIN32_STDOUT_HANDLE = -11
 WIN32_STDERR_HANDLE = -12

+# CSIDL constants (from MSDN 2003)
+CSIDL_APPDATA = 0x001A      # Application Data folder
+CSIDL_PERSONAL = 0x0005     # My Documents folder
+
+# from winapi C headers
+MAX_PATH = 260
+UNLEN = 256
+MAX_COMPUTERNAME_LENGTH = 31
+

 def get_console_size(defaultx=80, defaulty=25):
- -   """ Return size of current console.
- -
- -   This function try to determine actual size of current working
- -   console window and return tuple (sizex, sizey) if success,
- -   or default size (defaultx, defaulty) otherwise.
- -
- -   Dependencies: ctypes should be installed.
- -   """
- -   if not has_ctypes:
- -       # no ctypes is found
- -       return (defaultx, defaulty)
- -
- -   # To avoid problem with redirecting output via pipe
- -   # need to use stderr instead of stdout
- -   h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
- -   csbi = ctypes.create_string_buffer(22)
- -   res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
- -
- -   if res:
- -       (bufx, bufy, curx, cury, wattr,
+    """Return size of current console.
+
+    This function try to determine actual size of current working
+    console window and return tuple (sizex, sizey) if success,
+    or default size (defaultx, defaulty) otherwise.
+    """
+    if not has_ctypes:
+        # no ctypes is found
+        return (defaultx, defaulty)
+
+    # To avoid problem with redirecting output via pipe
+    # need to use stderr instead of stdout
+    h = ctypes.windll.kernel32.GetStdHandle(WIN32_STDERR_HANDLE)
+    csbi = ctypes.create_string_buffer(22)
+    res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
+
+    if res:
+        (bufx, bufy, curx, cury, wattr,
         left, top, right, bottom, maxx, maxy) =
struct.unpack("hhhhHhhhhhh", csbi.raw)
- -       sizex = right - left + 1
- -       sizey = bottom - top + 1
- -       return (sizex, sizey)
- -   else:
- -       return (defaultx, defaulty)
+        sizex = right - left + 1
+        sizey = bottom - top + 1
+        return (sizex, sizey)
+    else:
+        return (defaultx, defaulty)
+
+
+def get_appdata_location():
+    """Return Application Data location.
+    Return None if we cannot obtain location.
+
+    Returned value can be unicode or plain sring.
+    To convert plain string to unicode use
+    s.decode(bzrlib.user_encoding)
+    """
+    if has_ctypes:
+        try:
+            SHGetSpecialFolderPath = \
+                ctypes.windll.shell32.SHGetSpecialFolderPathW
+        except AttributeError:
+            pass
+        else:
+            buf = ctypes.create_unicode_buffer(MAX_PATH)
+            if SHGetSpecialFolderPath(None,buf,CSIDL_APPDATA,0):
+                return buf.value
+    # from env variable
+    appdata = os.environ.get('APPDATA')
+    if appdata:
+        return appdata
+    # if we fall to this point we on win98
+    # at least try C:/WINDOWS/Application Data
+    windir = os.environ.get('windir')
+    if windir:
+        appdata = os.path.join(windir, 'Application Data')
+        if os.path.isdir(appdata):
+            return appdata
+    # did not find anything
+    return None

^- I would imagine this might do really weird things with an
Internationalized version of Win98 (like they do with Program Files,
etc). But as long as it works some of the time, it is probably better
than what we have now.


...

+    # at least return windows root directory
+    windir = os.environ.get('windir')
+    if windir:
+        return os.path.splitdrive(windir) + '/'
+    # otherwise C:\ is good enough for 98% users
+    return 'C:/'

^- I thought there was something like "windrive". I know I have a friend
who installed his bootable windows onto E:/ and he has no end of pain
from apps that assume there *is* a 'C:/' and that it is the default drive.
But if "windir" gets us most of the way, we can go with it.


...

v- I would actually prefer to do ~/bzr.log on Windows, since $HOME does
not have the same meaning.

What I would really rather see is us changing from ~/.bzr.log to
~/.bazaar/bzr.log and %APPDATA%/Bazaar/2.0/bzr.log

That said, this is still better than what we've had.

+    if tracefilename is None:
+        if sys.platform == 'win32':
+            from bzrlib import win32utils
+            home = win32utils.get_home_location()
+        else:
+            home = os.path.expanduser('~')
+        tracefilename = os.path.join(home, '.bzr.log')
+
+    trace_fname = os.path.expanduser(tracefilename)

...
You can actually do "tf.seek(0, 1)", which tells it to move 0 characters
from the current position. Or you can do "tf.seek(0, 2)" which tells it
to seek to the end of the file.
That is a little better than writing out something first.

+        # tf.tell() on windows always return 0 until some writing done
+        tf.write('\n')
+        if tf.tell() <= 2:
+            tf.write("this is a debug log for diagnosing/reporting
problems in bzr\n")
             tf.write("you can delete or truncate this file, or include
sections in\n")
             tf.write("bug reports to bazaar at lists.canonical.com\n\n")
         _file_handler = logging.StreamHandler(tf)


Otherwise I'm happy with the changes. None of my comments have to be
done. So I'll leave it up to you to decide how you want to proceed.

John
=:->


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFFwj5VJdeBCYSNAAMRAv5uAKDEjzcgVcJ+IYmUNR762XKkO8p5YwCff5jx
zttRKic/9mI8WoAM6KyDf+Q=
=BbNZ
-----END PGP SIGNATURE-----



More information about the bazaar mailing list