tag:blogger.com,1999:blog-65209079785861037612024-03-18T10:47:27.251+01:00The grumbling smurfespenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.comBlogger39125tag:blogger.com,1999:blog-6520907978586103761.post-74367039337531929232011-11-01T09:21:00.002+01:002011-11-01T09:22:45.021+01:00Maintenance of malabar-modeAs some of my readers may have noticed, not much has happened to <a href="https://github.com/espenhw/malabar-mode">malabar-mode</a> in quite a while. I have simply been too busy, and have started using IntelliJ as my IDE of choice.<br />
<br />
So this is a call to interested parties: If anybody wants to take over malabar-mode, let me know and we'll work out the details.Espen Wiborghttp://www.blogger.com/profile/12897990282855652534noreply@blogger.com5tag:blogger.com,1999:blog-6520907978586103761.post-91919974840885366292011-08-22T13:53:00.001+02:002012-01-30T09:43:42.862+01:00Permanently fixing Realtek networking on Ubuntu NattySo here we are again. Kernel upgrade, then reboot => no network. Last week a kernel upgrade borked my network again, and it took a while before I remembered that I needed the r8168 module (see last posting).<br />
<br />
Today it happened again. So I think to myself "There must be a better way." It turns out there is: It is called DKMS, the "Dynamic Kernel Module Support". Essentially it works by registering the module for rebuild whenever the kernel is upgraded.<br />
<br />
<a name='more'></a><br />
Here's what I did:<br />
<ol>
<li>Copy the source code to <span style="font-family: "Courier New",Courier,monospace;">/usr/src/r8168-8.023.00</span> - the directory name must be <span style="font-family: "Courier New",Courier,monospace;">MODULE-VERSION</span></li>
<li>Create a dkms.conf: <hr />
<pre>PACKAGE_NAME="r8168"
PACKAGE_VERSION="8.023.00"
AUTOINSTALL="yes"
MAKE[0]="'make' modules"
BUILT_MODULE_NAME[0]="r8168"
BUILT_MODULE_LOCATION[0]="src"
DEST_MODULE_LOCATION[0]="/kernel/drivers/net"
</pre>
<hr />
</li>
<li>Tell DKMS about the module: <span style="font-family: "Courier New",Courier,monospace;">sudo dkms add -m r8168 -v 8.023.00</span></li>
<li>Build it: <span style="font-family: "Courier New",Courier,monospace;">sudo dkms build -m r8168 -v 8.023.00</span></li>
<li><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">And finally install it: <span style="font-family: "Courier New",Courier,monospace;">sudo dkms install </span></span></span><span style="font-family: "Courier New",Courier,monospace;">-m r8168 -v 8.023.00</span><span style="font-family: "Courier New",Courier,monospace;"> </span></li>
<li>At this point, you can use DKMS to build a deb package if you wish. In any case, further kernel upgrades will magically build and install the module.</li>
</ol>
<i>Update 2012-01-30: As pointed out by Ben Tebulin in a comment, the make command needs an extra level of quotes; see <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=553625">this Debian bugreport</a></i>.<br />
<ol>
</ol>espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com3tag:blogger.com,1999:blog-6520907978586103761.post-4463512816690978422011-05-03T23:14:00.000+02:002011-05-03T23:14:30.227+02:00Fixing Realtek networking on Ubuntu 11.04 (Natty Narwhal)<div style="font-family: inherit;">Tonight I made the mistake of upgrading my primary home work computer to Ubuntu 11.04 in the middle of a crunch period at work. I'd found the perfect time for it, I thought; start the upgrade and get the kids to bed while it runs (monitoring it every now and then). Once the kids are tucked in, I reboot the box. So what happens? </div><div style="font-family: inherit;"><br />
</div><div style="font-family: inherit;"><b>Boom!</b> no network. dmesg says <br />
<blockquote><span style="font-family: "Courier New",Courier,monospace;">r8169 0000:02:00.0: eth0: unable to apply firmware patch</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">r8169 0000:02:00.0: eth0: link down</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">ADDRCONF(NETDEV_UP): eth0: link is not ready</span></blockquote></div><div style="font-family: inherit;">Ouchie; I, like, uhm, <i><b>really</b></i> need net access for work.</div><div style="font-family: inherit;"><br />
</div><div style="font-family: inherit;">I'll elide the approximately four hours of increasingly panicky fiddling and Googling that occurred at this point; I feel my blood pressure rising just thinking about it.</div><div style="font-family: inherit;"><br />
</div><div style="font-family: inherit;">End of story: Check which Realtek chipset you have using <span style="font-family: "Courier New",Courier,monospace;">lspci</span>. Grab the appropriate proprietary driver, <a href="http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=1&PNid=13&PFid=5&Level=5&Conn=4&DownTypeID=3&GetDown=false">r8168</a> or <a href="http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=1&PNid=13&PFid=4&Level=5&Conn=4&DownTypeID=3&GetDown=false&Downloads=true">r8169</a> (hope for the 8168, the 8169 driver doesn't even compile without the changes <a href="http://vanvalkinburgh.org/blog/3537">this guy</a> details; luckily I have an 8168) and install it. I have net again!</div><div style="font-family: inherit;"><br />
</div><div style="font-family: inherit;">Now to do what I originally booted the box for.</div>espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com1tag:blogger.com,1999:blog-6520907978586103761.post-7453383919810757022010-10-12T23:00:00.001+02:002010-10-12T23:01:51.906+02:00OpenVPN with TomatoUSB sauce and TAP dancingI just bought a Netgear WNR3500L to replace my Linksys WRP400 wireless router. The main reason I bought that particular device is the Tomato firmware, specifically the TomatoUSB variant of it (at <a href="http://tomatousb.org/">http://tomatousb.org/</a>) which has OpenVPN support.<br />
<br />
Flashing the firmware was straightforward - I flashed the DD-WRT mini CHK firmware first, and then TomatoUSB (tomato-K26USB-1.28.9051MIPSR2-beta22-vpn3.6, to be precise). One hard reset later Tomato was running.<br />
<br />
So far it's been rock solid for me - time will tell how solid it really is. The only thing that has irked me so far is that it comes with a SIP ALG and SIP NAT-helper turned on by default - this plays havoc with work's equipment (yes, I'm currently in the VoIP business). Easy enough to turn off, though, once you know about it.<br />
<br />
Now for the OpenVPN setup. One thing that immediately struck me was that there is no way to set up auth-user-pass authentication (which is what work uses). But the "custom" option looks promising... Let's try it!<br />
<br />
Here's the basic page of my config:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/_5IxUEMLbcc4/TLTFq6O8tdI/AAAAAAAAAAM/PRDQtxLOOZs/s1600/client+basic.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="505" src="http://3.bp.blogspot.com/_5IxUEMLbcc4/TLTFq6O8tdI/AAAAAAAAAAM/PRDQtxLOOZs/s640/client+basic.png" width="640" /></a></div><br />
Note that interface type is TAP, Firewall is Automatic, and Create NAT on tunnel is checked.<br />
<br />
Now for the advanced page:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/_5IxUEMLbcc4/TLTH4rAB2lI/AAAAAAAAAAg/o9INl0nhx_M/s1600/client+advanced.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="502" src="http://1.bp.blogspot.com/_5IxUEMLbcc4/TLTH4rAB2lI/AAAAAAAAAAg/o9INl0nhx_M/s640/client+advanced.png" width="640" /></a></div><br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div>Here is the custom config. As there is no user to be queried for credentials when bringing up the tunnel, they need to be stored on disk somehow. I'll get to the "how" part later; for now, rest assured that /tmp/ca.crt and /tmp/client1-userpass will be available.<br />
<br />
Interesting to note here:<br />
<br />
<ol><li>We explicitly say that we're a client, as tomato only adds this automatically in the TLS mode; I figure this is a bug in TomatoUSB</li>
<li>We set script-security 3 (to tell OpenVPN that it's ok to run our up script)</li>
<li>We reference a script in /tmp as our up script; I'll get to why in a bit</li>
</ol>So how <b>are</b> the files in /tmp generated? At boot-time!<br />
<br />
Have a look at my init script:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/_5IxUEMLbcc4/TLTKNNFFfWI/AAAAAAAAAAk/AHgbrIkHMsQ/s1600/initscript.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/_5IxUEMLbcc4/TLTKNNFFfWI/AAAAAAAAAAk/AHgbrIkHMsQ/s1600/initscript.png" /></a></div><br />
<br />
<br />
Of course the values here aren't real. :)<br />
<br />
As you see, we stuff our credentials and the CA certificate in the files where we've told OpenVPN to look for them; we also generate the up script.<br />
<br />
The up script is as it is because of two other (IMAO) bugs in TomatoUSB:<br />
<ol><li>You cannot receive DNS server entries from the VPN server in custom mode; to work around this, we call out to the same script as would have been done in the other modes</li>
<li>Even though you can tell it to do NAT on the tunnel, and it will even generate the script to set it up (/etc/openvpn/fw/client1-fw.sh), it will never get run if the interface is not TUN.</li>
</ol>After all this, I now have always-on VPN on the router. :)espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com1tag:blogger.com,1999:blog-6520907978586103761.post-35006238140001536602010-10-12T21:46:00.000+02:002010-10-12T21:46:57.192+02:00Using SSH private keys with git and IntelliJ's "IDEA ssh" on WindowsDue to an unfortunate incident with my Linux laptop, I'm stuck working on my Windows gaming rig for a while. That is, of course, an adventure in itself; tonight's adventure was to get private SSH keys working on Windows when using IntelliJ's Git integration.<br />
<br />
First step, of course, was to try Pageant. No dice. Then I tried choosing "native ssh" - that just made IntelliJ hang (with no way to cancel - really nice GUI there, guys).<br />
<br />
Then the shoe dropped; maybe it pretends to be a "real" ssh client? One short check of my Windows home directory later I'd dropped my <code>id_rsa</code> private key file in %USERPROFILE%/.ssh, and IntelliJ happily picked it up.espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com29tag:blogger.com,1999:blog-6520907978586103761.post-6266277501178105742010-09-14T01:04:00.001+02:002010-09-14T01:11:41.264+02:00Speeding up database-bound tests with MySQL, reduxKinda long between the posts here; hopefully what I do write is worth waiting for. :)<br />
<br />
Way back in February I wrote about <a href="/2010/02/speeding-up-database-bound-tests-with.html">Speeding up database-bound tests with MySQL</a>; a nice chap named Adam Monsen <a href="http://article.gmane.org/gmane.comp.finance.mifos.devel/8684">used the idea</a> to speed up the build for something called <a href="http://mifos.org/">Mifos</a>.<br />
<br />
I've since thought of something that's worth adding:<br />
<br />
When you restart your computer with this setup, not only does your data go away (well, d'oh, you're storin' it in RAM, whaddaya expect?), but MySQL gets really confused about whether or not your table is there.<br />
<br />
If you know why this happens and want the short version, <a href="#conclusion">skip the exposition</a>.<br />
<br />
For the rest of us, let's see this in action:<br />
<br />
First we set the scene:<br />
<br />
<pre>espenhw@demokritos:~$ mysql -uroot
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 121
Server version: 5.1.41-3ubuntu12.6 (Ubuntu)
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create database confusion;
Query OK, 1 row affected (0.01 sec)
mysql> use confusion;
Database changed
mysql> create table confusion_levels (id bigint primary key, level varchar(255)) engine=innodb;
Query OK, 0 rows affected (0.06 sec)
mysql> insert into confusion_levels values (1, 'TOTAL');
Query OK, 1 row affected (0.00 sec)
mysql> show tables;
+---------------------+
| Tables_in_confusion |
+---------------------+
| confusion_levels |
+---------------------+
1 row in set (0.00 sec)
mysql> select * from confusion_levels;
+----+-------+
| id | level |
+----+-------+
| 1 | TOTAL |
+----+-------+
1 row in set (0.00 sec)
</pre><br />
All good. Now lets confuse MySQL:<br />
<br />
<pre>espenhw@demokritos:~$ sudo service mysql stop
mysql stop/waiting
espenhw@demokritos:~$ sudo ls -l /var/lib/mysql/innodb
total 20520
-rw-rw---- 1 mysql mysql 10485760 2010-09-14 00:41 ibdata1
-rw-rw---- 1 mysql mysql 5242880 2010-09-14 00:41 ib_logfile0
-rw-rw---- 1 mysql mysql 5242880 2010-09-13 08:16 ib_logfile1
espenhw@demokritos:~$ sudo umount /var/lib/mysql/innodb
espenhw@demokritos:~$ sudo mount /var/lib/mysql/innodb
espenhw@demokritos:~$ sudo ls -l /var/lib/mysql/innodb
total 0
# All gone!
espenhw@demokritos:~$ sudo service mysql start
mysql start/running, process 5388
</pre><br />
Let's see what MySQL says:<br />
<br />
<pre>mysql> show databases;
+--------------------------+
| Database |
+--------------------------+
[...redacted...]
| confusion |
[...redacted...]
+--------------------------+
mmysql> use confusion;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+---------------------+
| Tables_in_confusion |
+---------------------+
| confusion_levels |
+---------------------+
1 row in set (0.00 sec)
mysql> select * from confusion_levels;
ERROR 1146 (42S02): Table 'confusion.confusion_levels' doesn't exist
</pre><br />
Ehm, what? But it does exist, you said so yourself!<br />
<br />
Before you get bogged down in existential angst, there is a reasonable explanation.<br />
<br />
MySQL actually stores information about a database in separate files on disk. Metainformation (such as table structure) lives in files in a directory named for the database.<br />
<br />
Vide:<br />
<br />
<pre>espenhw@demokritos:~$ sudo ls -l /var/lib/mysql/confusion
total 16
-rw-rw---- 1 mysql mysql 8588 2010-09-14 00:50 confusion_levels.frm
-rw-rw---- 1 mysql mysql 65 2010-09-14 00:50 db.opt
</pre><br />
Digression: This is actually why MySQL is case-sensitive when it comes to database and table names, on case-sensitive file systems. So if you wondered why MySQL was more forgiving on Windows... Well, now you know.<br />
<br />
Data, on the other hand, lives in separate files. For a MyISAM-backed table, the files are named <code>tablename.MYD</code> and <code>tablename.MYI</code> (for data and indexes, respectively); InnoDB, on the other hand, holds data and indexes for all tables across the MySQL instance in the same files (actually, you can change this, but hardly anyone ever does).<br />
<br />
This clues us in to the solution to the above existential question: The table structure is still present, but the data is gone.<br />
<br />
<a name="conclusion"></a><br />
"Alright Espen, clever boy," I hear you say, "but what do I <b>DO</b> about it?"<br />
<br />
Well, you do what you should be doing anyway: Ensure that your tests start running with a clean slate. That means creating any tables it needs from scratch, i.e. either dropping the tables before recreating or simply drop/create on the whole database.<br />
<br />
For Hibernate, that should be as simple as setting the <code>hibernate.hbm2ddl.auto</code> property to <code>create-drop</code> (disclaimer: I haven't actually tested that); if you're running hand-crafted DDL to create your tables you probably know what to do...espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com11tag:blogger.com,1999:blog-6520907978586103761.post-19506490528939612072010-05-19T02:27:00.000+02:002010-05-19T02:27:38.135+02:00Scratching an itchSeveral times in the past years I've found myself wanting a Java client for the <a href="http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html">Apache JServ Protocol</a>, commonly used for communicating between a proxy/load balancer such as Apache and a servlet container such as Tomcat.<br />
<br />
The itch has never been bad enough to spend time on, but tonight I decided to go ahead and write one (never say that waiting for maintenance windows to roll around can't be spent productively!).<br />
<br />
So if this is the kind of thing that floats your boat, head on over to <a href="http://github.com/espenhw/ajp-client">GitHub</a> and grab your copy of the steaming hot <strike>pile of dung</strike> source code.espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com3tag:blogger.com,1999:blog-6520907978586103761.post-23475456681560725342010-02-17T19:42:00.000+01:002010-02-17T19:42:15.223+01:00Speeding up database-bound tests with MySQLIn my day job we use MySQL a lot, and we also like to pretend that we have tests.<br />
<br />
It's a good idea to run tests using the same database you're using in production, but MySQL ain't exactly a speed demon compared to memory-backed databases like Hypersonic, H2 or even Derby.<br />
<br />
But wait - we can have our cake and eat it, too!<br />
<br />
The trick is to tell MySQL to store its data files in memory; more specifically, the InnoDB files should be stored on a memory-backed filesystem like tmpfs.<br />
<br />
So, create a directory somewhere (I use /var/lib/mysql/innodb) and mount tmpfs on it (<code>mount -t tmpfs none /var/lib/mysql/innodb</code>, or set it up in /etc/fstab).<br />
<br />
After that, tell MySQL to store the InnoDB files there by sticking the following lines in /etc/mysql/my.cnf:<br />
<br />
<pre>innodb_data_home_dir=/var/lib/mysql/innodb
innodb_log_group_home_dir=/var/lib/mysql/innodb
</pre><br />
Now restart MySQL, and run your now-speedier tests!espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com34tag:blogger.com,1999:blog-6520907978586103761.post-48477341131207648102009-11-26T21:02:00.003+01:002009-11-26T21:49:43.840+01:00Gnus, IMAP and Exchange 2007My workplace upgraded its Exchange installation to Exchange 2007 over the weekend. As usual when Exchange is upgraded, the new and improved version also has a new and "improved" relationship to whatever standards it pretends to support.<br /><br />In this case it was IMAP that broke.<br /><br />First problem: During startup of Gnus, my echo area would be spammed with messages saying <code>BAD The specified message set is invalid</code>. Some googling later I had set the variable <code>imap-enable-exchange-bug-workaround</code> to <code>t</code>, which does pretty much what it says on the tin.<br /><br />So far, so good. But then I opened my inbox. Hm. Weren't there LOTS more mails here on Friday? Did the upgrade blat my mail? Hang on - didn't I see some junk in the echo area while Gnus worked. Let me try that again.<br /><br />Yes; lots of messages about <code>In imap-parse-body 2</code>. So I have a look at that function; all 90-odd lines of it. Apparently, something Exchange was sending made it fail an assertion.<br /><br />Unfortunately, the original function was hard to fix, not least because it was hard to tell what was failing. But isn't it really just reading a Lisp list? What if we let the reader help us?<br /><br />Some hacking later I ended up with this:<br /><pre>(defun imap-parse-body ()<br /> (when (eq (char-after) ?\()<br /> (nsubst nil 'NIL<br /> (imap-normalize-body-sexp (read (current-buffer))))))<br /><br />(defun imap-normalize-body-sexp (body-sexp)<br /> (dolist (m (imap-find-message-rfc822-parts body-sexp))<br /> (setf (nth 7 m) (apply 'vector (nth 7 m))))<br /> body-sexp)<br /><br />(defun imap-find-message-rfc822-parts (body)<br /> (flet ((rfc822-p (body)<br /> (and (stringp (car body))<br /> (string= "message" (car body))<br /> (string= "rfc822" (car (cdr body)))<br /> body)))<br /> (cond ((and (consp body) (atom (car body)))<br /> (rfc822-p body))<br /> ((consp body)<br /> (remove nil (mapcar 'imap-find-message-rfc822-parts body))))))</pre><br />The <code>imap-normalize-body-sexp</code> stuff isn't really necessary - all it does is turn a list into a vector, and since that vector is accessed using <code>elt</code> it works with a list, too. A vector is just more efficient.<br /><br />This code, simplistic as it may be, works for me (so far). If it works for you too, good; if it doesn't, there is no warranty.espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com1tag:blogger.com,1999:blog-6520907978586103761.post-40182657761035124562009-06-19T09:04:00.002+02:002009-06-19T09:06:31.128+02:00More puzzling behaviourStill in the spirit of <a href="http://javapuzzlers.com/">Java Puzzlers</a>; can you provide declarations for <code>i</code> and <code>j</code> to make this statement fail at runtime?<br /><br /><pre>i = j;</pre><br /><br />I spent quite some time debugging this, once...espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com2tag:blogger.com,1999:blog-6520907978586103761.post-38806784448938958422009-06-19T08:58:00.003+02:002009-06-19T09:04:37.573+02:00Puzzling behaviourIn the spirit of <a href="http://javapuzzlers.com/">Java Puzzlers</a>, what does this program print (if anything)?<br /><br /><pre>public class java<br />{<br /> static lang lang = new lang();<br /> <br /> static class lang<br /> {<br /> static Long Short = new Long();<br /> <br /> static class Short<br /> {<br /> }<br /><br /> static class Long<br /> extends Short<br /> {<br /> }<br /> }<br /> <br /> public static void main(String[] args) {<br /> System.out.println(java.lang.Short.class.getSimpleName());<br /> }<br />}</pre>espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com2tag:blogger.com,1999:blog-6520907978586103761.post-5311603158358435942009-02-25T21:34:00.002+01:002009-02-25T21:38:55.670+01:00Git == good<a href="http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#interrupted-work">git-stash</a> and <a href="http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#fixing-a-mistake-by-rewriting-history">git-commit --amend</a>. Killer features.<br /><br />Add to that excellent support for named branches, and <a href="http://www.kernel.org/pub/software/scm/git/docs/git-cherry-pick.html">git-cherry-pick</a>, and you've got yourself one wonderful DVCS.espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com1tag:blogger.com,1999:blog-6520907978586103761.post-17308308562626212009-01-05T14:38:00.001+01:002009-01-05T14:39:17.816+01:00Telling Skype which browser to use on UbuntuSkype (as the only thing on the planet, it seems) uses the x-www-browser alternative to open links. Fix that, and you're good to go.espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-67277271140304268812008-11-25T23:21:00.002+01:002008-11-25T23:29:01.841+01:00Fun on the bleeding edgeMy pet project <a href="http://www.bitbucket.org/espenhw/jde-mvn/">jde-mvn</a> depends on bleeding-edge snapshots of Maven 3.0. The reason is simple: MvnServer needs maven-embedder, which pre-3.0 is only available in a buggy and frankly unusable version 2.0.4.<br /><br />Mostly this is not a problem; however, the recent work Shane Isbell has done on the POM model breaks some existing POMs. Among them, unfortunately, is the CXF parent POM; this means that jde-mvn will choke on any project that depends on CXF (or any other POM that triggers the underlying bug). <br /><br />I've reported this issue as <a href="http://jira.codehaus.org/browse/MNG-3838">MNG-3838</a>; no word yet on when it will be fixed (although "sometime before 3.0 goes final" is a safe bet).<br /><br />Since some of the things I work on in my day job use CXF, I've made my own nastyhack version of Maven and created a "release" of jde-mvn that embeds it; read more about this "release" on the BitBucket site.espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-21520092767832892782008-11-24T22:55:00.002+01:002008-11-24T22:58:32.563+01:00More fun with JDEEWith jde-mvn having reached a more-or-less stable point, I've played with some other ideas to make JDEE an even better environment.<br /><br />One of these ideas is <a href="http://www.bitbucket.org/espenhw/jde-refactor/">jde-refactor</a>, which has now gotten far enough to unleash upon the unsuspecting masses. Er. Maybe there is one other person in the world who might find this useful?espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-19892394638474971952008-11-10T20:49:00.005+01:002008-11-10T21:01:34.461+01:00Running a secondary X serverSometimes it is useful to run a second (or third, or fourth...) X server for testing porpoises. I find this invaluable when hacking at window managers (such as my current favorite, <a href="http://awesome.naquadah.org/">awesome</a>).<br /><br />It is also occasionally useful to be able to kill an X server with impunity, e.g. to check how an application behaves when its X connection goes away.<br /><br />Even better: You can use this to deal with less-than-well-behaved programs that require a given resolution or color depth; I use it to be able to play Might and Magic VI full-screen using Wine, without having to fiddle with XRandR to get my resolution back afterwards.<br /><br />So how do I do this? Simple:<br /><pre>startx /path/to/program option1 option2 -- :1</pre><br />It really is that simple. If you wish, you can add more options after the double dash to pass them to the invoked X server. For instance, to run MM6 I do this:<br /><pre>startx $HOME/bin/mm6-core -- :1 -depth 16</pre><br />Where the <code>-depth 16</code> tells X that I want 16-bit color. <code>mm6-core</code> is simply a script that takes care of invoking Wine with the right options.espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-44453237172047029522008-10-07T23:30:00.004+02:002008-10-07T23:37:24.466+02:00jde-mvn moves to the bit bucketTonight I moved jde-mvn to <a href="http://bitbucket.org/">BitBucket</a>, the Mercurial world's answer to <a href="http://github.com/">GitHub</a>. Hopefully this will make it easier for other people to contribute (yeah, right); it's also a cool experiment for me to do.<br /><br />Check it out: <a href="http://bitbucket.org/espenhw/jde-mvn/wiki/">http://bitbucket.org/espenhw/jde-mvn/wiki/</a>. Also, please check out <a href="http://bitbucket.org/espenhw/jde-mvn/issues/">the issues list</a>, and report any bugs/comments there.espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-87620231647226822652008-10-02T23:11:00.002+02:002008-10-02T23:15:28.612+02:00jde-mvn updatesI just fixed a bug in jde-mvn where nothing would work. But it worked for me last week, honest!<br /><br />Many thanks to Tilman who made me aware of the problem; hopefully the problem I found is the problem you had...espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-25853187306213606572008-09-25T01:19:00.003+02:002008-09-25T01:34:29.003+02:00pom-parser is dead, long live jde-mvn!As some of you know (I know you're out there, freaks), I'm happily hacking away at my JDEE-Maven integration project. Up to now I have had two separate projects:<br /><ol><li>pom-parser, which dealt with getting information from the POM and into JDEE's variables</li><li>jde-mvn, which dealt with using Maven as a build tool</li></ol>This became cumbersome, and got in the way of some cool stuff I wanted to do. So I merged them. :)<br /><br />pom-parser is now deprecated; if you use it, you should move to jde-mvn.<br /><br />This shouldn't be onerous for the, like, two people besides me who use it (while I'm on the subject, if you use this please drop me a note!), even though most (all?) of the functions in pom-parser have changed names.<br /><br />jde-mvn is packaged as a JDEE plugin (for more on this, <a href="http://jdee.sourceforge.net/jdedoc/html/jde-ug/jde-ug-content.html#Plugins">read about plugins in the JDEE manual</a>), which means that the installation process is both simpler and more complicated, but ultimately I think this is the way I want to go.<br /><br />Anyway, jde-mvn now supports a server mode, thus amortizing the startup cost of the JVM across calls. Wee! The initial startup cost is quite heavy, though, but there is not much I can do about that.<br /><br />So. If you want to play with jde-mvn, it is available from <a href="http://svn.grumblesmurf.org/mercurial/jde-mvn/">my Mercurial repository</a>. I will try to keep even tip fairly stable (I do the major hacking on a local clone), but I will also tag what I consider to be stable revisions with 'stable-DATE'; if you don't fancy life on the severely-hemorrhaging edge, you may want to go with one of these.<br /><br />Enjoy!espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com1tag:blogger.com,1999:blog-6520907978586103761.post-12122955781599897642008-09-19T01:15:00.003+02:002008-09-19T01:26:49.270+02:00New features in pom-parserpom-parser just got a bit simpler; I now delegate the work of resolving artifacts to files in the file system to Maven (using the dependency:list goal with outputAbsoluteArtifactFilename=true). Less work for me, more robust system; it should now work out of the box if you have a non-standard local repository location (or if you're on Windows).<br /><br />There are also three notable bug fixes:<br /><ul><li>with-pom will no longer fall over if there is no POM; this allows you to have a single prj.el in the parent directory of all your source dirs without nastiness happening if you need to work on an Ant-based project</li><li>Newer versions of maven-help-plugin have changed the output format; pom-parser should now be able to find the effective POM regardless of the plugin version</li><li>The classpath order (as presented by Maven) is now preserved. This is only relevant if you're using Maven 2.0.9 or later; before 2.0.9, the classpath order as generated by Maven was non-deterministic anyway (!).</li></ul>Next up: Integrating with <a href="http://nexus.sonatype.org/">Nexus</a> for completion of artifacts (in pom-add-dependency).<br /><br />pom-parser is, as usual, <a href="http://svn.grumblesmurf.org/svn/pom-el/trunk/">available from my Subversion repository</a>.espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-52469706222421093962008-09-05T13:30:00.004+02:002008-09-05T14:14:26.402+02:00I just can't let this go unpublished...<pre>public class $_ {<br /> public static <$_> $_ $_($_ a) {<br /> return a;<br /> }<br /> public static <$_> void $_($_ ... $__) {<br /> for ($_ $_ : $__) {<br /> // \u000a\u0053\u0079\u0073tem\u002eo\u0075t\u002epr\u0069n\u0074\uu006c\u006e($_($_));<br /> }<br /> }<br /><br /> public static void \u006d\u0061\u0069\u006e(\u0053t\u0072i\u006e\u0067 ... $_) {<br /> $_($_);<br /> }<br />}</pre><br /><br />Or, even better:<br /><br /><pre>public class $_ {<br /> public static <$_> $_ $_($_ a) {<br /> return \u0061\u003b\u002f\u002f$!"#$&/($##ยง!"a;<br /> }<br /> public static <$_> void $_($_ ... $__) {<br /> for ($_ $_ : $__) {<br /> // \u000a\u0053\u0079\u0073tem\u002eo\u0075t\u002epr\u0069n\u0074($_($_));<br /> }<br /> }<br /><br /> public static void \u006d\u0061\u0069\u006e(\u0053t\u0072i\u006e\u0067 ... $_) {<br /> /*<br /> * \u002a\u002fif($_\u002ele\u006egth\u003d=0)$_=\u006ee\u0077 \u0053t\u0072i\u006e\u0067[]{\u002f\u002a\u002a\u002f"Obfuscated!"};\u002f\u002a<br /> */<br /> <br /> for (\u0053t\u0072i\u006e\u0067 _$ : $_) {<br /> $_(_$\u002es\u0070\u006ci\u0074(\u0022"));<br /> $_(\u0022\n"\u002c "")\u003b;<br /> }<br /> }<br />}</pre>espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-47229455980200200102008-09-05T13:18:00.001+02:002008-09-05T13:20:03.450+02:00More obfuscation funFrom <a href="http://blog.taragana.com/index.php/archive/writing-obfuscated-code-using-java-generics-part-1/">this blog entry</a> comes this gem:<br /><br /><pre>import java.util.Collection;<br />public class TestType {<br /> public static <Collection> Collection myMethod(Collection a) {<br /> return a;<br /> }<br /> public static void main(String ... args) {<br /> System.out.println(myMethod("Hello World"));<br /> }<br />}</pre><br /><br />Beautiful, just beautiful...espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-45482073400752901592008-09-02T18:15:00.015+02:002008-09-03T20:07:02.928+02:00The joy of programmingToday I had occasion to rediscover the joy of programming. Not that it's been dull lately, far from it, but today I did something real <span style="font-style: italic;">fun</span>. Today's word is 'obfuscation'.<br /><span id="fullpost"><br />It started when I directed a colleague to <a href="http://www.ioccc.org/">The International Obfuscated C Code Contest</a>. Obfuscation is just so <span style="font-style: italic;">easy</span> in C; but can the same kind of thing be done in Java? Well...<br /><br />Inspired particularly by the Mullender entry from the very first IOCCC, in 1984, I sat down and thought.<br /><br />Here is what I came up with:<br /><pre>public class Obfuscated {<br /> static String n, m;<br /> static java.util.Map<String,byte[]> bm = new java.util.HashMap<String,byte[]>();<br /> static {<br /> try {<br /> n = new String(new byte[] {79,66,70,85,67,76,65,83,83}, "UTF-8");<br /> bm.put(n, new byte[] {<br /> 120,-100,109,80,93,75,2,65,20,61,-41,<br /> -81,117,-73,45,77,-45,62,5,95,34,-19,33,-95,87,-93,<br /> -88,64,8,36,-125,45,95,122,-102,-43,81,70,118,103,<br /> 67,103,-125,126,86,61,20,-12,-48,15,-24,71,69,<br /> 119,77,-112,-64,121,-72,-9,-50,-103,115,-18,61,119,<br /> -66,127,62,-65,0,-100,-94,70,-80,123,87,-99,-121,<br /> -21,-18,-91,-25,89,32,66,113,34,-98,69,43,16,122,<br /> -36,-22,-7,19,57,48,22,-46,-124,66,-49,31,-59,-77,<br /> -127,48,114,120,-110,16,8,-71,51,-91,-107,57,39,<br /> -92,27,-51,-66,-117,28,44,7,25,-28,9,-103,80,40,<br /> 77,-88,54,30,-69,-53,86,-98,-103,42,61,110,55,-5,<br /> -1,6,120,47,51,35,67,11,46,119,-119,98,67,-88,-4,<br /> 73,84,-44,-70,99,-66,97,-107,20,97,-37,-59,6,10,<br /> 54,-42,81,-28,-74,55,51,125,100,-22,-47,-62,-114,<br /> -118,116,125,20,-21,-117,60,74,-124,-14,10,-79,-123,<br /> 45,-126,-11,-108,0,1,-69,-86,52,86,-103,114,81,<br /> -59,-74,-125,10,118,-40,-2,117,52,-108,-68,112,87,<br /> 105,121,27,-121,-66,-100,-34,11,63,96,-60,-15,-94,<br /> 120,58,-112,29,21,72,16,82,-68,108,114,82,92,-13,<br /> -18,28,-9,-8,86,-29,76,-100,-77,-57,31,-80,95,<br /> -71,32,-20,115,-52,-51,65,-2,106,56,88,91,80,15,-25,<br /> 82,-64,126,-61,102,-87,-4,-114,-35,37,-35,-31,<br /> 39,36,-97,-119,44,35,7,-13,41,-39,95,48,-4,89,-18<br /> });<br /><br /> m = new String(new byte[] {109,97,105,110}, "UTF-8");<br /> } catch (java.io.UnsupportedEncodingException e) {<br /> }<br /> }<br /><br /> public static void main(String[] a) throws Exception {<br /> ClassLoader cl = new ClassLoader() {<br /> protected Class<?> findClass(String cn) throws ClassNotFoundException {<br /> if (bm.containsKey(cn)) {<br /> try {<br /> java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();<br /> java.util.zip.InflaterOutputStream ios = new java.util.zip.InflaterOutputStream(baos);<br /> ios.write(bm.get(cn));<br /> ios.close();<br /> byte[] bytes = baos.toByteArray();<br /> return defineClass(cn, bytes, 0, bytes.length);<br /> } catch (java.io.IOException e) {<br /> throw new ClassNotFoundException(cn, e);<br /> }<br /> } else {<br /> return super.findClass(cn);<br /> }<br /> }<br /> };<br /><br /> Class<?> c = Class.forName(n, true, cl);<br /><br /> for (java.lang.reflect.Method me : c.getDeclaredMethods()) {<br /> if (m.equals(me.getName()))<br /> me.invoke(null, (Object)a);<br /> }<br /> }<br />}</pre><font size="-1">You can <a href="http://java.grumblesmurf.org/Obfuscated.java">download this code</a></font>.<br />Not as pithy as Mullender's, but it still has a certain something.<br /><br />Now, of course, I didn't write that monstrous byte array by hand; in fact, the entire program above was written by another program, which is listed below:<br /><br /><pre>public class Obfuscator {<br /> static String n, m;<br /> static java.util.Map<String,byte[]> bm = new java.util.HashMap<String,byte[]>();<br /> static {<br /> try {<br /> n = new String(new byte[] {79,66,70,85,67,76,65,83,83}, "UTF-8");<br /> bm.put(new String(new byte[] {77,101,116,104,111,100,82,101,110,97,109,101,114}, "UTF-8"),<br /> new byte[] {<br /> 120,-100,-107,84,-51,78,19,81,24,61,-73,<br /> 45,20,-38,-31,-81,-108,42,34,32,32,-38,118,40,<br /> 69,65,65,1,21,17,-76,74,107,34,-124,-123,-69,-95,<br /> -67,-64,-32,48,37,-19,-16,-93,111,-30,-54,37,91,77,<br /> 68,-125,11,-29,-54,-123,-113,-32,11,-8,14,-58,-120,<br /> -25,78,-85,-87,-76,42,-90,-55,-52,-67,-33,-49,<br /> 57,-25,-98,-5,77,63,125,127,-9,30,-64,101,-36,23,<br /> 104,74,75,103,61,-97,123,36,109,99,83,22,-4,16,2,<br /> -67,-7,-62,90,50,-65,-78,33,-77,-50,-82,92,73,26,<br /> -59,-51,100,-87,104,38,103,108,57,-86,-56,43,16,<br /> -6,-83,111,120,-61,-40,49,4,26,-14,86,46,-61,125,<br /> 81,-96,101,65,-123,-110,-37,-114,105,37,23,-91,51,<br /> 41,-32,-73,-27,-82,74,-78,-73,-108,-77,12,123,45,<br /> -71,-24,20,76,123,-115,105,-49,-26,-114,64,-33,-62,<br /> -97,-72,-105,-51,-94,-23,-28,11,44,-84,-97,50,<br /> 109,-45,-71,33,48,23,-3,103,-11,49,17,-43,-68,-79,<br /> 101,-127,-13,-1,-58,-119,45,107,-48,-48,28,-128,<br /> 15,45,26,2,8,54,-62,-125,54,13,-11,-16,-85,85,-69,<br /> -122,6,52,-86,85,7,29,-35,81,77,75,79,-73,100,-54,<br /> 46,-38,2,-111,104,-86,54,111,-45,111,-30,-4,-24,<br /> -92,-127,-39,-68,-19,24,-90,77,3,59,-94,21,93,15,<br /> 93,109,-109,-79,-57,26,-70,112,54,-120,51,-24,-2,<br /> -53,61,-107,85,-5,-47,-85,-31,20,78,7,113,14,125,<br /> 2,-51,-82,-82,121,83,90,-71,-110,-80,-21,-75,-124,<br /> -99,36,-94,-60,123,87,-51,61,-127,11,-47,26,-39,<br /> -22,-112,-122,65,92,8,-48,-98,-117,26,6,112,94,9,<br /> -118,113,68,92,65,37,-55,74,-111,6,-67,-108,27,-94,<br /> 17,38,7,-51,-32,33,-108,127,-79,-118,107,76,-107,<br /> -29,-60,28,70,82,57,49,-62,-127,-86,-50,-5,113,<br /> -103,35,-73,110,20,51,114,-49,-95,-36,-88,-14,110,<br /> 12,87,-126,24,-59,85,1,-97,-19,-122,-61,-47,88,<br /> -75,-53,26,38,112,77,-43,93,23,104,61,126,22,63,-90,<br /> -120,107,-38,57,-71,-9,112,-11,-40,45,-3,52,32,<br /> -91,-31,6,110,6,48,-115,91,2,-127,-126,-36,-78,-116,<br /> -84,-100,-79,44,-127,-119,26,-27,39,116,-16,54,<br /> 102,21,-30,29,106,-97,-51,-25,-92,-6,-62,76,91,<br /> 102,-74,55,87,100,97,-55,88,-79,24,105,90,116,-116,<br /> -20,-109,-76,-79,85,-34,7,22,-13,-37,-123,-84,-100,<br /> 55,45,-119,62,-70,-17,-29,71,-17,-27,-101,83,<br /> -53,-107,71,-51,-84,-5,-26,60,-13,93,7,-63,25,111,<br /> -30,115,-98,-69,-23,114,125,71,92,127,-117,-42,-72,<br /> 126,-128,80,124,-24,0,-31,120,-30,0,-111,87,76,<br /> 8,-36,-27,51,-62,54,-80,-83,-114,-115,1,52,-93,-123,<br /> -65,48,90,-103,-27,-32,-107,-95,30,-112,-44,-53,<br /> 119,79,-4,53,-62,67,-121,-24,-15,-32,57,26,-72,<br /> -119,-92,-7,8,117,49,-44,-17,-59,43,87,-118,-62,<br /> 12,-71,-60,-19,68,12,115,29,65,55,-79,-18,-71,-46,<br /> 69,-120,-112,28,-96,50,-16,42,79,-94,-24,39,42,-127,<br /> -69,92,76,-123,-98,-120,119,-6,-34,34,122,-120,<br /> 120,29,-10,121,16,-105,-85,50,120,-100,-14,12,41,<br /> -69,56,-86,-35,24,71,-81,75,-23,-125,103,-80,-115,<br /> 108,-6,127,115,38,106,113,38,-86,57,-5,-55,57,<br /> 64,-50,65,114,94,-84,-32,-12,-88,79,-90,-52,-7,-116,<br /> 71,87,-75,-41,-12,-113,-72,-86,120,15,113,73,32,<br /> 77,-10,113,65,-10,1,46,-8,-65,-8,1,-45,25,61,-15,<br /> 6,51,-98,23,71,95,-12,-124,82,-13,6,115,11,-5,71,<br /> -97,-11,-105,-65,72,123,-36,-85,-113,19,78,-25,<br /> 109,37,-24,-20,48,71,35,-55,-56,8,5,-116,-71,2,-126,<br /> -16,124,67,-77,31,-93,95,17,-91,-126,-108,-37,<br /> 92,-9,3,-68,-120,101,94<br /> });<br /> bm.put(new String(new byte[] {67,108,97,115,115,82,101,110,97,109,101,114}, "UTF-8"),<br /> new byte[] {<br /> 120,-100,-83,84,91,79,19,65,20,-2,-90,<br /> -76,93,104,-73,92,-54,117,1,11,5,-124,-19,-115,42,<br /> 34,-105,114,81,44,-96,-43,82,-116,24,-116,-6,-76,<br /> -76,11,44,46,109,-45,46,-105,-8,-32,-1,-48,23,31,<br /> 125,-43,68,32,-43,-60,-8,-60,-125,63,-63,63,-32,<br /> 127,48,68,60,-77,20,-71,-76,4,30,-52,38,-77,51,-25,<br /> -100,-7,-50,-9,-51,-100,51,63,-2,124,-7,6,96,0,<br /> -113,25,-60,-88,-82,-28,-13,79,-44,-76,-78,-82,-26,<br /> 4,48,6,79,38,-73,18,-50,44,-83,-87,73,99,75,93,<br /> 10,43,-7,-11,-80,25,51,-107,82,-78,6,-113,-87,96,<br /> -112,74,99,-26,-77,-55,76,74,-51,11,-80,49,-44,-99,<br /> 6,-19,95,83,54,21,-122,-54,-116,-98,74,-48,58,<br /> -49,80,19,-25,-90,-16,-122,-95,-23,-31,5,-43,24,99,<br /> 16,-46,-22,22,119,50,-72,-113,124,-70,-110,94,9,<br /> 47,24,57,45,-67,66,110,-5,-72,-106,-42,-116,73,-122,<br /> 105,57,126,1,-69,69,45,-81,25,-103,-36,-40,57,<br /> -24,82,52,-33,34,67,-9,-91,48,-66,69,17,34,-86,29,<br /> -80,-94,70,68,37,-86,-86,96,65,-99,8,7,-100,124,<br /> 86,-49,96,-37,-28,-95,12,9,57,22,43,-51,114,21,-53,<br /> -53,-14,-28,92,103,20,8,104,102,-88,80,82,41,-122,<br /> 70,-7,-44,-122,121,-109,-5,-104,-17,-123,8,9,<br /> -83,78,-76,-96,-115,-63,-110,-36,100,-24,-68,76,-101,<br /> -120,107,-16,112,21,29,23,95,118,49,86,-128,87,<br /> 68,35,-102,-100,-24,66,55,-125,-45,-44,60,-89,26,<br /> -85,25,-30,-77,46,-1,71,-31,101,72,31,-27,57,102,<br /> 77,-89,-80,-84,109,51,-12,-54,-27,118,-105,-104,<br /> 68,-12,65,118,-112,72,-97,-120,-21,-24,-27,2,2,116,<br /> -74,71,-104,-1,-54,61,-60,48,83,-82,22,-50,-90,<br /> -66,66,77,-15,106,9,59,-48,-113,27,12,29,-105,-32,<br /> 9,24,-96,118,-48,-88,-105,20,90,49,52,-55,-66,83,<br /> 25,98,69,59,41,24,-60,109,126,-79,67,-44,21,-91,<br /> 126,1,35,-44,55,-85,74,62,-95,110,83,25,86,-56,-68,<br /> 20,34,24,115,98,20,-29,12,-42,-76,105,110,-112,<br /> 125,-91,69,35,98,18,119,120,-36,93,-122,-38,-13,<br /> 98,4,-36,35,92,45,-99,82,-73,-25,-105,-49,21,-35,<br /> -79,-36,-104,-120,105,-52,56,16,-59,44,-125,35,-89,<br /> 102,117,37,-87,78,-23,58,-61,72,-103,-16,43,-34,<br /> -41,3,-60,56,-30,67,-30,30,-91,-105,-124,63,19,90,<br /> 90,77,108,-84,47,-87,-71,-89,-54,-110,78,22,-41,<br /> -126,-95,36,95,-51,41,-39,-30,-38,-79,-112,-39,-56,<br /> 37,-43,89,77,87,-31,-91,-69,-74,-126,-34,10,-6,<br /> 91,120,-57,-46,11,-25,-26,-3,74,127,110,23,-31,-94,<br /> 49,78,-85,65,51,18,-88,-11,7,-10,104,8,-18,-64,<br /> -19,15,-19,-96,-31,19,-39,24,-26,-52,125,-36,-17,<br /> -126,13,-43,-124,80,67,95,45,121,-88,15,-118,8,83,<br /> 16,-24,3,-68,-2,-49,112,-121,10,104,-73,-32,25,<br /> 77,59,-37,-84,52,54,72,86,-55,38,-39,11,-24,17,112,<br /> 2,89,-115,10,26,-21,-119,78,3,58,9,-118,-15,-86,<br /> 44,-62,101,-120,52,-121,-101,48,49,-126,-2,-48,30,<br /> -4,126,-55,74,-93,100,43,32,104,71,-60,46,-39,-9,<br /> -31,105,-85,-77,-30,-51,59,52,125,69,-1,115,-55,<br /> -50,115,-13,116,123,-72,-55,-3,31,9,-64,114,-118,<br /> 125,11,90,-23,101,-24,-93,49,-126,118,36,-56,82,<br /> 9,118,-128,-120,-128,91,20,71,-51,81,76,-2,-102,-120,<br /> -15,-8,-47,-64,62,-122,56,102,1,-61,68,57,88,<br /> -64,4,-61,91,116,-45,100,-118,-31,59,-94,-119,64,<br /> 104,23,-9,45,-17,15,127,5,66,60,-17,46,30,-59,63,<br /> 28,-2,12,-100,36,-10,28,29,10,-63,117,-111,-34,30,<br /> 52,-109,70,47,-87,-12,83,-70,97,4,76,18,78,88,14,<br /> 80,45,96,-12,-73,-55,96,-34,-36,44,-4,5,18,3,-92,<br /> -11<br /> });<br /> bm.put(n, new byte[] {<br /> 120,-100,-107,87,121,120,27,-59,21,-1,<br /> -115,108,107,-27,-107,18,-37,74,-28,-80,4,-110,37,<br /> 64,34,57,-118,12,118,49,65,54,9,62,48,56,-8,0,-100,<br /> -60,56,110,74,-41,-46,-38,86,34,-19,-118,-43,<br /> 42,-119,49,38,16,82,-96,-123,-74,20,122,81,-24,-107,<br /> -46,-70,119,33,-76,50,-58,77,74,75,47,40,-67,40,<br /> -67,75,79,-38,-46,-5,-8,-89,31,-3,10,-18,-101,93,<br /> -55,-110,34,-39,-112,-3,108,-51,-18,-101,119,-49,<br /> -69,-26,-23,87,30,63,9,-96,9,-1,98,-88,30,-24,-24,<br /> -34,-43,-39,-37,62,56,40,-128,49,-44,-18,83,14,<br /> 40,-115,113,69,27,111,28,24,-35,-89,70,76,1,21,12,<br /> -110,110,-116,55,-22,-42,-9,65,117,-76,81,73,37,<br /> 26,7,-110,17,61,-86,-90,4,84,49,-44,12,-116,-114,<br /> -91,83,17,-59,-44,-115,16,-89,103,112,-74,-59,-76,<br /> -104,-71,-115,-95,-62,31,-40,-19,-127,11,-43,34,<br /> 42,33,50,84,38,-108,-104,-58,80,-17,31,-23,-51,75,<br /> 26,52,-115,-104,54,-34,26,-40,-51,-80,42,15,-67,<br /> -4,80,68,77,-102,49,93,19,-80,-78,72,-79,-63,-55,<br /> -108,-87,38,4,-44,18,123,-43,48,24,124,54,-81,-104,<br /> -34,120,53,49,50,-119,-99,-86,36,90,61,-16,98,<br /> 85,53,-22,-80,-102,97,79,58,-91,-116,-85,97,57,-81,<br /> -88,-36,22,-119,43,-87,-108,-90,36,-44,109,114,<br /> 91,66,53,39,-12,-88,-87,-57,-76,3,-6,126,14,-32,112,<br /> 125,44,66,-116,76,53,106,97,110,-109,71,-38,-108,<br /> 104,52,-58,53,82,-30,54,40,20,10,-19,117,-95,62,<br /> -89,118,-79,2,2,-50,96,16,-110,28,16,39,-109,125,<br /> -2,114,22,123,112,38,-42,-118,-112,112,22,-7,70,<br /> 61,20,51,105,-15,-9,112,-8,58,-84,23,73,121,89,-124,<br /> -125,59,-82,-62,72,19,-109,-34,50,76,94,11,-92,<br /> -84,-73,61,56,23,-25,113,-10,-25,-77,-86,71,-109,<br /> -23,-47,120,44,34,91,118,-55,83,23,76,-53,-101,<br /> -90,54,-119,50,61,41,83,49,105,-61,-90,-110,-75,-96,<br /> -100,104,45,-124,115,-66,-95,-76,25,-117,-121,<br /> -6,-108,100,-101,-115,21,28,-99,52,-43,-111,-67,-37,<br /> -28,-47,-124,124,-87,-84,-87,7,11,-80,-82,84,82,<br /> 19,-91,-104,-2,64,17,-45,-100,108,-2,-104,-58,100,<br /> -47,55,127,52,98,59,117,-31,116,-85,56,-43,52,<br /> 93,-76,-63,-27,77,53,79,-73,46,2,-89,101,58,-19,-56,<br /> -124,-20,-73,52,-120,-23,-95,93,90,42,-99,76,-22,<br /> 6,29,-21,-27,26,-123,48,41,-79,24,104,-78,26,40,<br /> 18,101,-13,-98,22,-83,37,-21,-96,-84,-122,7,-12,<br /> 88,84,-26,-79,-20,-73,13,25,-39,43,43,1,-39,-100,<br /> 48,-12,-125,41,57,-49,-80,-112,91,39,119,109,-81,<br /> -82,68,85,-125,-36,-100,117,76,1,-48,31,40,-79,51,<br /> 105,-24,38,-27,-100,26,-75,-15,-38,-74,111,-109,<br /> -57,98,90,-44,-6,-56,10,-106,35,-38,-94,92,11,-34,<br /> -81,-101,-35,122,90,-117,-106,87,34,-9,-60,-58,<br /> 100,-1,104,34,20,-47,53,-109,-116,72,93,-91,78,-6,<br /> -119,81,-87,6,-53,-99,66,-31,-109,115,111,7,-99,<br /> 103,-69,97,40,-109,3,105,51,-103,-50,102,-126,60,<br /> -86,-24,-87,-62,72,88,10,49,23,6,75,74,-80,66,-24,<br /> -58,88,50,-44,-93,-115,-59,41,53,-115,34,49,-79,<br /> 98,41,-53,34,-5,-71,78,-53,-120,35,94,-95,-125,70,<br /> -52,84,-71,-101,-58,85,-45,114,-49,-14,-24,-111,<br /> -72,-98,82,-105,51,-63,14,118,107,-31,-118,114,13,<br /> 66,-90,-66,-24,-119,-27,72,13,-43,76,27,-102,28,<br /> 85,-23,-4,85,-5,-4,35,-108,-117,22,-85,-96,124,65,<br /> -10,45,20,87,-75,113,115,98,9,62,37,-71,-48,51,-80,<br /> 100,-24,-97,-6,88,17,-106,-113,-40,-110,32,-77,<br /> -76,81,-105,18,92,2,-99,-106,-43,120,74,93,82,98,<br /> -42,90,-54,84,-43,8,-27,35,-98,-114,-96,84,64,49,<br /> -13,-4,23,21,-127,-30,-44,-29,-39,19,33,-73,91,31,<br /> -95,49,-35,-24,-89,26,-17,39,-75,77,35,-83,6,41,<br /> 37,3,5,20,-76,-99,-11,19,-81,-103,33,67,29,-117,<br /> 83,34,-122,-6,-84,62,33,39,84,57,44,71,120,88,116,<br /> -87,84,49,13,53,106,111,-92,-4,101,82,-120,-89,90,<br /> 34,-92,-34,-112,86,-30,41,127,66,-27,84,-106,-28,<br /> 64,32,80,98,12,109,-37,45,-56,-81,-91,-29,-15,-96,<br /> -20,-73,-101,112,64,41,48,60,87,-107,-90,93,-40,<br /> -60,-80,-58,42,-20,60,-44,27,123,99,-38,126,53,<br /> -54,11,-20,-96,74,125,59,32,-94,-127,119,-114,21,<br /> 121,12,11,30,-92,102,66,-115,-20,-108,-114,100,11,<br /> 106,13,-20,-15,32,-124,70,55,-74,-32,2,-122,-70,<br /> 60,105,-74,110,11,104,18,-47,-52,-39,-70,40,55,12,<br /> -34,73,121,55,15,-12,-26,49,123,-78,112,106,-64,<br /> 23,-95,-123,115,-70,-104,-63,91,-70,47,-32,18,-22,<br /> -113,19,74,-86,95,61,100,90,-109,2,-55,110,69,-101,<br /> 27,97,92,74,109,80,-77,-64,-85,115,-68,11,-75,<br /> -12,96,59,46,-29,120,-19,-59,-125,-127,85,17,5,116,<br /> -110,118,-28,101,-21,-96,-87,55,23,113,-80,-128,<br /> -60,-32,114,116,-13,-111,-28,-118,-100,7,11,24,116,<br /> -92,99,113,-86,-57,2,122,68,-20,-32,-90,10,-122,<br /> -102,-116,43,17,-107,91,-38,-39,25,40,-19,-91,30,<br /> -12,-94,79,68,23,-6,105,-12,81,-110,73,85,35,-9,<br /> 110,41,-41,-16,75,64,89,97,-60,-30,106,92,-61,-27,<br /> 93,75,44,66,86,27,118,97,39,25,98,-22,54,-30,-87,<br /> -82,88,20,-67,27,67,-100,-18,58,-102,-61,78,49,<br /> 83,-64,30,50,-97,60,113,-83,-102,-46,-45,70,68,109,<br /> 79,-39,-59,-113,33,-80,-76,114,52,-59,-12,104,-117,<br /> 117,-110,4,-68,30,123,69,-116,-32,13,12,103,-105,<br /> -50,-127,-106,-96,107,85,-59,114,-40,27,25,-50,<br /> -16,-105,-27,98,79,-127,-93,34,20,68,-106,-26,51,<br /> -60,11,46,-15,81,57,50,-115,63,99,32,-77,-41,45,<br /> -127,-36,30,85,-110,22,118,-116,-31,92,127,-17,18,<br /> 88,-69,99,-87,24,15,70,91,-127,-3,34,-10,33,78,<br /> 30,-74,-45,-47,3,13,-115,-4,-36,-12,-110,88,-73,82,<br /> -27,6,17,6,68,23,31,-116,61,89,67,-7,96,72,50,-45,<br /> 12,93,-81,42,-77,-73,40,-13,-54,-116,101,-74,82,<br /> 7,69,28,-64,33,30,57,17,94,77,25,-50,123,85,-50,<br /> -42,-124,120,35,-90,-72,63,111,34,127,-26,92,94,<br /> -74,-85,10,-72,89,-60,97,30,-56,27,-14,10,81,95,108,<br /> -20,82,75,-5,-94,-128,91,105,-34,-49,31,98,-31,<br /> 94,86,-33,-37,68,28,-63,81,6,119,65,-17,-30,99,107,<br /> 96,-92,-61,-125,-37,113,7,63,-73,59,25,-86,-84,<br /> -10,73,-85,127,-92,-125,19,-66,5,119,113,-62,-69,<br /> 9,98,117,74,15,-34,-58,-81,5,71,-16,118,-122,115,<br /> 120,103,-55,-74,-57,-87,-78,45,-63,-123,119,112,<br /> -39,107,121,-88,-33,-57,-51,33,9,78,-69,-35,89,-75,<br /> -93,-57,-125,119,-29,61,124,-9,-67,12,103,-47,8,<br /> -67,108,-90,-67,-113,35,62,-64,17,-53,-92,115,33,<br /> -30,-5,57,-30,7,-88,86,46,-95,-44,-121,-56,112,34,<br /> 74,120,112,-116,-89,97,23,62,66,21,-87,20,-19,-93,<br /> -92,44,-115,89,-86,65,-89,27,-14,-9,-100,94,97,<br /> -104,-63,-57,-71,22,-97,-96,-53,90,74,53,123,45,<br /> -101,61,-8,20,79,-112,29,-8,52,-43,-42,-46,-98,-24,<br /> -62,103,11,46,37,5,-119,40,-32,97,17,-113,112,-105,<br /> 23,-76,5,-85,-82,63,74,110,36,52,-122,-83,101,<br /> -38,66,-103,70,81,-82,42,127,1,25,55,62,-113,89,<br /> -78,118,-65,58,73,49,79,105,85,-44,27,120,26,120,<br /> 48,-121,-57,57,-38,60,-87,88,-88,53,13,90,-92,-128,<br /> -33,-123,19,12,76,115,-31,75,100,-80,-98,-67,-80,<br /> 81,28,109,124,77,-11,-108,-40,127,25,95,-31,-73,<br /> -102,39,25,28,65,-14,-3,-41,-8,74,73,-4,13,50,112,<br /> -100,-85,-76,-79,92,-33,43,103,-50,83,120,-102,<br /> -21,-7,45,-18,-8,-12,104,42,91,-122,125,-27,-126,<br /> -117,-80,-65,-115,-17,-16,0,-8,46,-119,-95,110,-19,<br /> -62,-9,-23,69,79,-101,30,-4,-64,-66,-122,62,-105,<br /> 107,53,38,53,-74,-58,62,53,-59,-81,-92,-35,-70,<br /> -111,80,-88,-46,-4,-120,92,54,102,-67,51,92,82,-58,<br /> -48,-111,-27,85,94,84,-30,39,-8,-87,-120,31,-29,<br /> 103,-28,-38,50,119,62,1,-65,32,103,-116,116,8,-8,<br /> 37,85,-103,92,120,44,119,37,18,-16,107,82,-101,103,<br /> -89,-51,-62,95,-104,-88,46,-4,-106,-110,121,-41,<br /> -50,-18,45,91,93,120,-63,110,-70,-68,34,-92,120,<br /> -93,44,115,88,-68,62,-4,1,127,-28,94,122,-111,-54,<br /> -57,116,80,-34,96,17,111,8,-72,-16,103,74,-92,78,<br /> 61,74,-25,92,67,115,-116,-38,-97,78,-116,-86,-58,<br /> 78,101,52,78,-112,21,-125,-90,18,-39,79,81,-102,<br /> -3,22,23,-43,35,73,-30,-96,-43,-38,-70,99,113,21,<br /> 100,28,-11,116,114,37,96,-83,46,84,-45,-17,95,-23,<br /> -21,108,90,25,-83,85,13,-77,112,63,66,47,12,127,<br /> -93,95,-89,5,-84,39,52,15,86,16,49,71,-67,14,85,<br /> 22,116,83,-61,73,-25,49,-44,28,-121,-49,-69,38,-125,<br /> -77,43,31,-61,57,-13,112,12,-49,98,67,67,69,83,<br /> 67,101,83,67,85,83,67,6,27,57,51,-121,-59,-84,-98,<br /> 8,65,-9,121,39,-42,98,37,-50,-126,23,-21,-79,17,<br /> 50,-2,78,-48,10,48,47,-2,-111,85,-85,-122,-2,-23,<br /> -22,109,-53,-85,124,-103,8,-42,16,-113,125,94,127,<br /> -40,57,-113,6,-110,-80,57,44,72,-62,-26,57,92,-24,<br /> -64,-112,84,121,-46,-7,16,-50,113,-74,-72,124,<br /> 46,122,63,-122,122,73,-112,42,125,-82,38,123,-5,-88,<br /> -117,-51,44,-68,56,-113,102,34,123,93,-40,37,9,<br /> 115,-40,-54,16,-82,-106,-86,-25,-80,-115,-31,126,<br /> -74,-99,-65,117,48,60,-127,-82,-80,72,10,95,57,-113,<br /> 29,-124,123,-107,36,-42,-122,106,27,51,24,-56,<br /> 96,-48,-69,-117,126,50,24,-50,-32,-6,-80,123,30,<br /> -54,-80,-28,-98,69,52,-20,-103,-57,-40,-80,115,22,<br /> 19,-31,21,-13,-40,55,44,-83,-104,69,34,-68,82,18,<br /> 55,103,-112,-68,31,-21,-25,97,16,-93,84,-72,-58,<br /> 107,-122,107,-25,113,-128,16,-92,26,-87,118,22,-109,<br /> -124,-28,-111,86,86,100,48,61,-113,-61,-124,115,<br /> 75,-72,102,30,71,-122,-91,-102,89,-68,41,92,43,<br /> -43,74,43,50,120,115,6,111,-107,106,51,-72,-121,-21,<br /> -29,-67,119,22,-17,12,-41,73,53,25,-68,43,-20,<br /> -107,-68,39,91,86,85,-76,-84,-10,-83,-10,-83,58,-122,<br /> 54,-55,-21,91,-35,-36,-30,-109,-22,50,-72,-65,<br /> -91,94,-86,-13,-7,50,120,-80,54,-104,-63,7,-121,<br /> 124,-11,-75,-35,73,107,-125,-42,-121,-32,-106,-22,<br /> -68,31,38,83,-122,-114,-82,38,-81,60,-55,57,-13,<br /> 77,-78,-21,33,-30,95,-31,-3,88,6,-97,36,41,117,22,<br /> 69,101,52,-125,-49,16,-63,-25,56,-127,-28,-50,-32,<br /> -72,-28,-110,68,11,127,14,-113,85,96,104,-26,-107,<br /> 19,89,95,-111,59,93,115,-8,34,-125,-19,92,81,18,<br /> 109,-25,-30,14,-2,-106,117,-82,91,114,-37,-114,<br /> 113,121,-51,25,84,73,-18,-80,71,-86,-10,-98,36,-18,<br /> -7,-115,39,102,80,-35,32,121,102,-15,-43,34,-16,<br /> -41,9,-33,-5,-51,2,-48,26,82,-59,61,-121,103,28,<br /> -100,115,45,121,-23,123,51,-88,41,-124,-15,67,123,<br /> -106,43,62,-77,-112,110,-16,-102,-60,-112,14,55,<br /> -56,23,-9,113,-4,80,114,10,39,80,57,92,-79,101,112,<br /> -72,82,18,7,-121,-85,-92,-22,-63,97,-89,-28,30,<br /> 124,12,63,-89,80,-50,-121,-20,113,4,-23,119,35,69,<br /> 101,47,-59,127,31,-123,112,63,-91,-54,0,-4,-44,-6,<br /> 46,-94,-75,21,59,41,89,119,33,66,83,-26,29,24,-62,<br /> -67,-108,29,15,98,-104,90,-46,30,60,76,51,-31,<br /> 28,13,-121,39,-80,23,-49,-32,122,60,71,-77,-56,-13,<br /> 24,-59,-117,-124,-3,111,68,-15,31,-116,49,7,13,<br /> 112,-21,49,-63,54,-46,-112,-42,-116,125,-84,19,-5,<br /> -39,85,4,-69,6,9,54,1,-115,-103,52,121,-35,-124,<br /> 36,-69,21,6,-69,7,41,118,31,13,86,15,-30,0,123,2,<br /> 7,-39,-77,56,-28,-72,8,-45,-114,-83,56,-20,-72,12,<br /> -73,56,-82,-64,17,71,12,-73,-15,116,98,79,-63,-69,<br /> 64,-103,85,45,-64,33,-96,43,-9,-9,60,-84,-91,-127,<br /> -78,-9,-65,56,-13,101,-44,9,104,22,16,94,-64,-51,<br /> -88,41,-113,105,35,88,-17,-113,8,80,4,-116,9,52,<br /> 32,98,-127,-116,-10,-99,6,-123,-128,-61,2,-114,<br /> 8,-40,33,-32,87,52,43,-30,101,-70,-38,-80,-105,80,<br /> -75,-128,118,-120,-53,-15,-31,-94,-22,-31,94,6,101,<br /> -121,-123,-11,63,-100,75,-80,118,-6,-25,-8,43,<br /> 94,5,-33,-34,0,-93,-81,5,-86,73,-81,17,-35,97,125,<br /> 117,93,109,81,-79,-45,-92,-70,-34,-94,114,-97,38,<br /> -43,75,68,-111,47,-118,14,-34,-71,-77,69,-8,1,-86,<br /> -104,2,-83,125,86,117,-8,29,101,111,-33,102,-17,<br /> -17,51,-8,83,-1,-106,-109,45,-107,21,45,85,-66,42,<br /> 95,-27,49,-84,-35,-30,-85,106,110,113,6,125,-50,<br /> -59,-110,112,-76,-118,82,-1,-123,96,48,-105,-31,<br /> 65,-17,95,120,-98,-48,-9,-16,-61,-117,113,-65,-50,<br /> 98,126,59,68,-118,-22,-13,113,39,46,-92,-11,98,-102,<br /> 80,-37,113,23,-82,-60,-35,86,-55,62,3,-114,5,<br /> -6,113,-26,44,-54,29,-18,-70,69,-107,127,67,-1,-1,<br /> -76,120,10,-1,7,0,126,-15,92<br /> });<br /><br /> m = new String(new byte[] {109,97,105,110}, "UTF-8");<br /> } catch (java.io.UnsupportedEncodingException e) {<br /> }<br /> }<br /><br /> public static void main(String[] a) throws Exception {<br /> ClassLoader cl = new ClassLoader() {<br /> protected Class<?> findClass(String cn) throws ClassNotFoundException {<br /> if (bm.containsKey(cn)) {<br /> try {<br /> java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();<br /> java.util.zip.InflaterOutputStream ios = new java.util.zip.InflaterOutputStream(baos);<br /> ios.write(bm.get(cn));<br /> ios.close();<br /> byte[] bytes = baos.toByteArray();<br /> return defineClass(cn, bytes, 0, bytes.length);<br /> } catch (java.io.IOException e) {<br /> throw new ClassNotFoundException(cn, e);<br /> }<br /> } else {<br /> return super.findClass(cn);<br /> }<br /> }<br /> };<br /><br /> Class<?> c = Class.forName(n, true, cl);<br /><br /> for (java.lang.reflect.Method me : c.getDeclaredMethods()) {<br /> if (m.equals(me.getName()))<br /> me.invoke(null, (Object)a);<br /> }<br /> }<br />}</pre><font size="-1">You can <a href="http://java.grumblesmurf.org/Obfuscator.java">download this code, too</a></font>.<br />You'll need to have <a href="http://asm.objectweb.org/">ASM</a> 3.0 or later on your classpath to run this.<br /><br />Happy hacking, and remember, kids:<br /><br />If it ain't fun, you ain't doin' it right!<br /><br />Final (hopefully) edit: Updated the example and the obfuscator to actually work. Wee.<br /><br />Really final and last edit (2008-09-03): Tweaked the obfuscator to produce smaller class files, allows obfuscation of more complicated classes without bumping into JVM limits.<br /></span>espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-67957436700019486042008-06-03T01:26:00.003+02:002008-06-03T01:46:46.662+02:00Next step, world dominationMy JDEE/Maven integration work is proceeding apace; pom-parser is now learning to modify the POM. The first evidence of this is the command <code>pom-add-dependency</code>, which allows you to add a dependency element to your POM. It even does completing-reads of groupId, artifactId and version!<br /><br />It doesn't reparse the POM when it changes, though. I know how to do it, I just haven't gotten around to it yet; besides, I'm not sure if I want it to. Maybe it should be a customizable option?<br /><br />I've also fixed one genuine bug (I only changed the <span style="font-weight: bold;">first</span> dot in the groupId to a slash... oops) and one unexpected behavior:<br /><br />Imagine a file structure where you have a <code>src</code> directory with two Maven projects inside, <code>foo</code> and <code>bar</code>. You have a generic <code>prj.el</code> file in the <code>src</code> directory.<br /><br />If you visit a Java file from project foo, the foo POM is read and JDEE variables are set correctly; then visit a file from project bar, and the bar POM is read and JDEE variables set.<br /><br />But if you then switch back to the file from the foo project, you will get bar's variable settings (e.g. classpath). Bummer.<br /><br />Once I twigged to what was going on, though ("Dude, why is this file not compiling? Hang on, that classpath looks strange...") it was fairly easy to fix.<br /><br /><hr/><br /><br />In other news, I have more-or-less ready code to use Maven as a build tool for JDEE (ala the Ant integration); I just want to hammer it a bit more before I make it public.<br /><br />And I may have a solution for the "making JDEE wait for Maven" issue <a href="http://blog.grumblesmurf.org/2008/05/exciting-developments-in-pom-parser.html">mentioned a couple of weeks ago</a>. Once again, stay tuned!espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0tag:blogger.com,1999:blog-6520907978586103761.post-8993561361794598112008-06-03T01:06:00.003+02:002008-06-03T01:25:47.707+02:00Bidirectional Mercurial + SVNI've been playing with <a href="http://www.selenic.com/mercurial">Mercurial</a> lately, and I'm really impressed. However, I still need to interact with Subversion repositories (not least my own), so I thought I'd try <a href="http://pypi.python.org/pypi/hgsvn/">hgsvn</a>, which lets you use Mercurial locally on a Subversion checkout. Sweetness!<br /><br />That is, as long as you remember to tell Emacs that you prefer Mercurial to Subversion by moving the 'Hg' entry before 'SVN' in vc-handled-backends...<br /><br />One wrinkle, though: hgsvn does not handle pushing changes back to the remote repo...<br /><br />But that's nothing a little shell scripting can't fix!<br /><br /><a href="http://svn.grumblesmurf.org/svn/bash/hgpushsvn/hgpushsvn.sh">hgpushsvn.sh</a> lets you do just that. <br /><br />Run it like this: <code>hgpushsvn.sh mono[lithic]|single</code><br /><br /><dl><br /> <dt>monolithic (or mono)</dt><br /> <dd>Checks in all changes since the last revision in Subversion as one commit. The commit message is the output of <code>hg log --style changelog</code> for the changesets back to the last pulled from Subversion.</dd><br /> <dt>single</dt><br /> <dd>Checks in each changeset since the last pull as a separate commit. The commit message is still the output of <code>hg log --style changelog</code>. This is a much slower operation!</dd><br /></dl>espenhwhttp://www.blogger.com/profile/02349981324214517542noreply@blogger.com0